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

use metadata;
use frame;
use subframe;

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

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

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

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

fn parser<'a>(input: &'a [u8], is_start: &mut bool)
              -> IResult<&'a [u8], Metadata> {
  let mut slice = input;

  if *is_start {
    let (i, _) = try_parse!(slice, tag!("fLaC"));

    slice     = i;
    *is_start = false;
  }

  metadata_parser(slice)
}

impl
 Stream
 where P: StreamProducer {
  /// Constructor for the default state of a FLAC stream.
  ///
  /// This doesn't actually decode anything, it just hold the default values
  /// of each field.
  pub fn new() -> Stream {
    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    }
  }

  /// Returns information for the current stream.
  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.
  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.
  pub fn from_file(filename: &str) -> io::Result<Stream> {
    File::open(filename).and_then(|file| {
      let mut producer = ReadStream::new(file);
      let error_str    = format!("parser: couldn't parse the given file {}",
                                 filename);

      Stream::from_stream_producer(&mut 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.
  pub fn from_buffer(buffer: &[u8]) -> io::Result<Stream> {
    let mut producer = ByteStream::new(buffer);
    let error_str    = "parser: couldn't parse the buffer";

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

  fn from_stream_producer
(producer: &mut P, error_str: &str)
                             -> io::Result<Stream>
   where P: StreamProducer {
    let mut is_error = false;
    let mut stream   = Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    };

    loop {
      match stream.handle(producer) {
        Ok(_)                      => break,
        Err(ErrorKind::EndOfInput) => break,
        Err(ErrorKind::Continue)   => continue,
        Err(_)                     => {
          is_error = true;

          break;
        }
      }
    }

    if !is_error {
      let channels    = stream.info.channels as usize;
      let block_size  = stream.info.max_block_size as usize;
      let output_size = block_size * channels;

      stream.output.reserve_exact(output_size);

      unsafe { stream.output.set_len(output_size) }

      Ok(stream)
    } else {
      Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
    }
  }

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

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

  fn next_frame<'a>(&'a mut self) -> Option<&'a [i32]> {
    if self.frames.is_empty() || self.frame_index >= self.frames.len() {
      None
    } else {
      let frame       = &self.frames[self.frame_index];
      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);

      self.frame_index += 1;

      Some(&self.output[0..(block_size * channels)])
    }
  }

  fn handle_marker<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(0);

    match tag!(input, "fLaC") {
      IResult::Done(i, _)    => {
        self.state = ParserState::Metadata;

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_metadata<'a>(&mut self, input: &'a [u8])
                         -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(1);

    match metadata_parser(input) {
      IResult::Done(i, block) => {
        let is_last = block.is_last;

        if let metadata::Data::StreamInfo(info) = block.data {
          self.info = info;
        } else {
          self.metadata.push(block);
        }

        if is_last {
          self.state = ParserState::Frame;
        }

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_frame<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(2);

    match frame_parser(input, &self.info) {
      IResult::Done(i, frame) => {
        self.frames.push(frame);

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle<S: StreamProducer>(&mut self, stream: &mut S)
                               -> Result<(), ErrorKind> {
    stream.parse(|input| {
      match self.state {
        ParserState::Marker   => self.handle_marker(input),
        ParserState::Metadata => self.handle_metadata(input),
        ParserState::Frame    => self.handle_frame(input),
      }
    })
  }
}

/// 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 {
      let frame_index = self.stream.frame_index;

      if self.stream.next_frame().is_none() {
        return None;
      } else {
        let frame = &self.stream.frames[frame_index];

        self.sample_index = 0;
        self.block_size   = frame.header.block_size as usize;
      }
    }

    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>;

  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<commit_msg>Change from_stream_producer type signature<commit_after>use nom;
use nom::{Err, IResult};

use metadata;
use frame;
use subframe;

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

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

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

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

fn parser<'a>(input: &'a [u8], is_start: &mut bool)
              -> IResult<&'a [u8], Metadata> {
  let mut slice = input;

  if *is_start {
    let (i, _) = try_parse!(slice, tag!("fLaC"));

    slice     = i;
    *is_start = false;
  }

  metadata_parser(slice)
}

impl
 Stream
 where P: StreamProducer {
  /// Constructor for the default state of a FLAC stream.
  ///
  /// This doesn't actually decode anything, it just hold the default values
  /// of each field.
  pub fn new() -> Stream {
    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    }
  }

  /// Returns information for the current stream.
  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.
  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.
  pub fn from_file(filename: &str) -> io::Result<Stream> {
    File::open(filename).and_then(|file| {
      let mut producer = ReadStream::new(file);
      let error_str    = format!("parser: couldn't parse the given file {}",
                                 filename);

      Stream::from_stream_producer(&mut 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.
  pub fn from_buffer(buffer: &[u8]) -> io::Result<Stream> {
    let mut producer = ByteStream::new(buffer);
    let error_str    = "parser: couldn't parse the buffer";

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

  fn from_stream_producer(mut producer: P, error_str: &str)
                          -> io::Result<Self> {
    let mut is_error = false;
    let mut stream   = Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    };

    loop {
      match stream.handle(producer) {
        Ok(_)                      => break,
        Err(ErrorKind::EndOfInput) => break,
        Err(ErrorKind::Continue)   => continue,
        Err(_)                     => {
          is_error = true;

          break;
        }
      }
    }

    if !is_error {
      let channels    = stream.info.channels as usize;
      let block_size  = stream.info.max_block_size as usize;
      let output_size = block_size * channels;

      stream.output.reserve_exact(output_size);

      unsafe { stream.output.set_len(output_size) }

      Ok(stream)
    } else {
      Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
    }
  }

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

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

  fn next_frame<'a>(&'a mut self) -> Option<&'a [i32]> {
    if self.frames.is_empty() || self.frame_index >= self.frames.len() {
      None
    } else {
      let frame       = &self.frames[self.frame_index];
      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);

      self.frame_index += 1;

      Some(&self.output[0..(block_size * channels)])
    }
  }

  fn handle_marker<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(0);

    match tag!(input, "fLaC") {
      IResult::Done(i, _)    => {
        self.state = ParserState::Metadata;

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_metadata<'a>(&mut self, input: &'a [u8])
                         -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(1);

    match metadata_parser(input) {
      IResult::Done(i, block) => {
        let is_last = block.is_last;

        if let metadata::Data::StreamInfo(info) = block.data {
          self.info = info;
        } else {
          self.metadata.push(block);
        }

        if is_last {
          self.state = ParserState::Frame;
        }

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_frame<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(2);

    match frame_parser(input, &self.info) {
      IResult::Done(i, frame) => {
        self.frames.push(frame);

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle<S: StreamProducer>(&mut self, stream: &mut S)
                               -> Result<(), ErrorKind> {
    stream.parse(|input| {
      match self.state {
        ParserState::Marker   => self.handle_marker(input),
        ParserState::Metadata => self.handle_metadata(input),
        ParserState::Frame    => self.handle_frame(input),
      }
    })
  }
}

/// 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 {
      let frame_index = self.stream.frame_index;

      if self.stream.next_frame().is_none() {
        return None;
      } else {
        let frame = &self.stream.frames[frame_index];

        self.sample_index = 0;
        self.block_size   = frame.header.block_size as usize;
      }
    }

    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>;

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


<commit_before>use std::os::raw::{c_int, c_double, c_void};

use ffi;
use base::*;

extern "C" fn wrapper<T: Fn(OutStream, i32, i32)>(raw_out: *mut ffi::SoundIoOutStream,
                                                  min: c_int,
                                                  max: c_int) {
    let out = OutStream::new(raw_out);
    let cb_ptr = unsafe { (*out.stream).userdata as *const *const T };
    let cb: &T = unsafe { &*(*cb_ptr) };
    cb(out, min, max);
}

pub struct OutStream {
    // TODO: make this private again after
    // implementint the callback register methods
    pub stream: *mut ffi::SoundIoOutStream,
}
impl OutStream {
    pub fn new(raw_stream: *mut ffi::SoundIoOutStream) -> Self {
        OutStream { stream: raw_stream }
    }

    pub fn open(&self) -> Option<ffi::SioError> {
        match unsafe { ffi::soundio_outstream_open(self.stream) } {
            ffi::SioError::None => None,
            err @ _ => Some(err),
        }
    }

    pub fn start(&self) -> Option<ffi::SioError> {
        match unsafe { ffi::soundio_outstream_start(self.stream) } {
            ffi::SioError::None => None,
            err @ _ => Some(err),
        }
    }

    pub fn register_write_callback<T: Fn(OutStream, i32, i32)>(&mut self, callback: Box<T>) {
        let userdata = &*callback as *const T as *mut c_void;
        unsafe {
            (*self.stream).userdata = userdata;
            (*self.stream).write_callback = Some(wrapper::<T>);
        }
    }

    pub fn begin_write(&self,
                       areas: *mut *mut ffi::SoundIoChannelArea,
                       frame_count: *mut c_int)
                       -> Option<ffi::SioError> {
        match unsafe { ffi::soundio_outstream_begin_write(self.stream, areas, frame_count) } {
            ffi::SioError::None => None,
            err @ _ => Some(err),
        }
    }

    pub fn end_write(&self) -> Option<ffi::SioError> {
        match unsafe { ffi::soundio_outstream_end_write(self.stream) } {
            ffi::SioError::None => None,
            err @ _ => Some(err),
        }
    }

    pub fn clear_buffer(&self) -> Option<ffi::SioError> {
        match unsafe { ffi::soundio_outstream_clear_buffer(self.stream) } {
            ffi::SioError::None => None,
            err @ _ => Some(err),
        }
    }

    pub fn pause(&self, pause: bool) -> Option<ffi::SioError> {
        let pause_c_bool = match pause {
            true => 1u8,
            false => 0u8,
        };
        match unsafe { ffi::soundio_outstream_pause(self.stream, pause_c_bool) } {
            ffi::SioError::None => None,
            err @ _ => Some(err),
        }
    }

    pub fn get_latency(&self) -> Result<f64, ffi::SioError> {
        let mut latency = 0.0f64;
        match unsafe {
            ffi::soundio_outstream_get_latency(self.stream, &mut latency as *mut c_double)
        } {
            ffi::SioError::None => Ok(latency),
            err @ _ => Err(err),
        }

    }

    pub fn current_format(&self) -> Result<ffi::SioFormat, ffi::SioError> {
        match unsafe { (*self.stream).format } {
            ffi::SioFormat::Invalid => Err(ffi::SioError::Invalid),
            fmt @ _ => Ok(fmt),
        }
    }

    pub fn get_layout(&self) -> ChannelLayout {
        ChannelLayout::new(unsafe { &(*self.stream).layout })
    }

    pub fn get_sample_rate(&self) -> i32 {
        unsafe { (*self.stream).sample_rate as i32 }
    }

    pub fn get_device(&self) -> Device {
        let dev = Device::new(unsafe { (*self.stream).device });
        dev.inc_ref();
        dev
    }

    pub fn destroy(&self) {
        unsafe { ffi::soundio_outstream_destroy(self.stream) }
    }
}
impl Drop for OutStream {
    fn drop(&mut self) {
        // TODO: call destroy manually.
        // OutStream will get dropped each time a new
        // struct is created from the same *mut pointer.
    }
}
<commit_msg>Update TODO<commit_after>use std::os::raw::{c_int, c_double, c_void};

use ffi;
use base::*;

extern "C" fn wrapper<T: Fn(OutStream, i32, i32)>(raw_out: *mut ffi::SoundIoOutStream,
                                                  min: c_int,
                                                  max: c_int) {
    let out = OutStream::new(raw_out);
    let cb_ptr = unsafe { (*out.stream).userdata as *const *const T };
    let cb: &T = unsafe { &*(*cb_ptr) };
    cb(out, min, max);
}

pub struct OutStream {
    // TODO: make this private again
    // - add a struct that contains the registered callback closures, this could look like this:
    // struct Callbacks<W: Fn(OutStream, i32, i32), U: Fn(OutStream), E: Fn(OutStream, SioError)> {
    //      // maybe Option<Box<W>>
    //      write_callback: Option<W>,
    //      underflow_callback: Option<U>,
    //      error_callback: Option<E>,
    // }
    // impl Default for Callbacks<W: Fn(OutStream, i32, i32), U: Fn(OutStream), E: Fn(OutStream, SioError)> {
    //      fn default() -> Self {
    //          Callbacks {
    //              write_callback: None,
    //              underflow_callback: None,
    //              error_callback: None,
    //          }
    //      }
    // }
    pub stream: *mut ffi::SoundIoOutStream,
}
impl OutStream {
    pub fn new(raw_stream: *mut ffi::SoundIoOutStream) -> Self {
        OutStream { stream: raw_stream }
    }

    pub fn open(&self) -> Option<ffi::SioError> {
        match unsafe { ffi::soundio_outstream_open(self.stream) } {
            ffi::SioError::None => None,
            err @ _ => Some(err),
        }
    }

    pub fn start(&self) -> Option<ffi::SioError> {
        match unsafe { ffi::soundio_outstream_start(self.stream) } {
            ffi::SioError::None => None,
            err @ _ => Some(err),
        }
    }

    pub fn register_write_callback<T: Fn(OutStream, i32, i32)>(&mut self, callback: Box<T>) {
        let userdata = &*callback as *const T as *mut c_void;
        unsafe {
            (*self.stream).userdata = userdata;
            (*self.stream).write_callback = Some(wrapper::<T>);
        }
    }

    pub fn begin_write(&self,
                       areas: *mut *mut ffi::SoundIoChannelArea,
                       frame_count: *mut c_int)
                       -> Option<ffi::SioError> {
        match unsafe { ffi::soundio_outstream_begin_write(self.stream, areas, frame_count) } {
            ffi::SioError::None => None,
            err @ _ => Some(err),
        }
    }

    pub fn end_write(&self) -> Option<ffi::SioError> {
        match unsafe { ffi::soundio_outstream_end_write(self.stream) } {
            ffi::SioError::None => None,
            err @ _ => Some(err),
        }
    }

    pub fn clear_buffer(&self) -> Option<ffi::SioError> {
        match unsafe { ffi::soundio_outstream_clear_buffer(self.stream) } {
            ffi::SioError::None => None,
            err @ _ => Some(err),
        }
    }

    pub fn pause(&self, pause: bool) -> Option<ffi::SioError> {
        let pause_c_bool = match pause {
            true => 1u8,
            false => 0u8,
        };
        match unsafe { ffi::soundio_outstream_pause(self.stream, pause_c_bool) } {
            ffi::SioError::None => None,
            err @ _ => Some(err),
        }
    }

    pub fn get_latency(&self) -> Result<f64, ffi::SioError> {
        let mut latency = 0.0f64;
        match unsafe {
            ffi::soundio_outstream_get_latency(self.stream, &mut latency as *mut c_double)
        } {
            ffi::SioError::None => Ok(latency),
            err @ _ => Err(err),
        }

    }

    pub fn current_format(&self) -> Result<ffi::SioFormat, ffi::SioError> {
        match unsafe { (*self.stream).format } {
            ffi::SioFormat::Invalid => Err(ffi::SioError::Invalid),
            fmt @ _ => Ok(fmt),
        }
    }

    pub fn get_layout(&self) -> ChannelLayout {
        ChannelLayout::new(unsafe { &(*self.stream).layout })
    }

    pub fn get_sample_rate(&self) -> i32 {
        unsafe { (*self.stream).sample_rate as i32 }
    }

    pub fn get_device(&self) -> Device {
        let dev = Device::new(unsafe { (*self.stream).device });
        dev.inc_ref();
        dev
    }

    pub fn destroy(&self) {
        unsafe { ffi::soundio_outstream_destroy(self.stream) }
    }
}
impl Drop for OutStream {
    fn drop(&mut self) {
        // TODO: call destroy manually.
        // OutStream will get dropped each time a new
        // struct is created from the same *mut pointer.
    }
}
<|endoftext|>


<commit_before>use node::{Node};
use std::slice::Iter;
use std::vec::IntoIter;
use std::cmp::PartialEq;
use std::fmt;

/// Triple segment.
#[derive(PartialEq, Debug)]
pub enum TripleSegment {
  Subject,
  Predicate,
  Object
}

/// Triple representation.
#[derive(Clone, Debug)]
pub struct Triple {
  subject: Node,
  predicate: Node,
  object: Node
}

impl Triple {
  /// Constructor for Triple struct.
  ///
  /// Requires subject, predicate and object nodes.
  ///
  /// # Examples
  ///
  /// todo
  ///
  pub fn new(subject: Node, predicate: Node, object: Node) -> Triple {
    Triple {
      subject: subject.clone(),
      predicate: predicate.clone(),
      object: object.clone()
    }
  }

  /// Returns a reference to the subject node of the triple.
  pub fn subject(&self) -> &Node {
    &self.subject
  }

  /// Returns a reference to the predicate node of the triple.
  pub fn predicate(&self) -> &Node {
    &self.predicate
  }

  /// Returns a reference to the object node of the triple.
  pub fn object(&self) -> &Node {
    &self.object
  }
}

impl PartialEq for Triple {
  fn eq(&self, other: &Triple) -> bool {
    self.subject() == other.subject() &&
    self.predicate() == other.predicate() &&
    self.object() == other.object()
  }
}

impl Eq for Triple { }

/// Storage for triples.
#[derive(Debug)]
pub struct TripleStore {
  triples: Vec<Triple>
}

impl TripleStore {
  /// Constructs a new triple store.
  pub fn new() -> TripleStore {
    TripleStore {
      triples: Vec::new()
    }
  }

  /// Returns the number of triples that are stored.
  pub fn count(&self) -> usize {
    self.triples.len()
  }

  /// Checks if the triple store is empty.
  pub fn is_empty(&self) -> bool {
    self.count() == 0
  }

  /// Adds a new triple to the store.
  pub fn add_triple(&mut self, triple: &Triple) {
    self.triples.push(triple.clone());
  }

  /// Deletes the triple from the store.
  pub fn remove_triple(&mut self, triple: &Triple) {
    self.triples.retain(|ref t| {
      *t != triple
    });
  }

  /// Returns all triples where the subject node matches the provided node.
  ///
  /// # Example
  ///
  /// todo
  ///
  pub fn get_triples_with_subject(&self, node: &Node) -> Vec<&Triple> {
    self.triples.iter().filter(|t| t.subject() == node).collect::<Vec<_>>()
  }

  /// Returns all triples where the predicate node matches the provided node.
  ///
  /// # Example
  ///
  /// todo
  ///
  pub fn get_triples_with_predicate(&self, node: &Node) -> Vec<&Triple> {
    self.triples.iter().filter(|t| t.predicate() == node).collect::<Vec<_>>()
  }

  /// Returns all triples where the object node matches the provided node.
  ///
  /// # Example
  ///
  /// todo
  ///
  pub fn get_triples_with_object(&self, node: &Node) -> Vec<&Triple> {
    self.triples.iter().filter(|t| t.object() == node).collect::<Vec<_>>()
  }

  /// Returns all triples where the subject and object nodes match the provided nodes.
  ///
  /// # Example
  ///
  /// todo
  ///
  pub fn get_triples_with_subject_and_object(&self, subject_node: &Node, object_node: &Node) -> Vec<&Triple> {
    self.triples.iter().filter(|t|
      t.object() == object_node && t.subject() == subject_node
    ).collect::<Vec<_>>()
  }

  /// Returns all triples where the subject and predicate nodes match the provided nodes.
  ///
  /// # Example
  ///
  /// todo
  ///
  pub fn get_triples_with_subject_and_predicate(&self, subject_node: &Node, predicate_node: &Node) -> Vec<&Triple> {
    self.triples.iter().filter(|t|
      t.predicate() == predicate_node && t.subject() == subject_node
    ).collect::<Vec<_>>()
  }

  /// Returns all triples where the predicate and object nodes match the provided nodes.
  ///
  /// # Example
  ///
  /// todo
  ///
  pub fn get_triples_with_predicate_and_object(&self, predicate_node: &Node, object_node: &Node) -> Vec<&Triple> {
    self.triples.iter().filter(|t|
      t.predicate() == predicate_node && t.object() == object_node
    ).collect::<Vec<_>>()
  }

  /// Returns all blank nodes of the store.
  pub fn get_blank_nodes(&self) -> Vec<&Node> {
    let mut blank_nodes = Vec::new();

    for triple in self.triples.iter() {
      match triple {
        &Triple { subject: Node::BlankNode {id : _}, predicate: _, object: Node::BlankNode {id : _} } => {
          blank_nodes.push(triple.subject());
          blank_nodes.push(triple.object());
        },
        &Triple { subject: Node::BlankNode {id : _}, predicate: _, object: _ } =>
          blank_nodes.push(triple.subject()),
        &Triple { subject: _, predicate: _, object: Node::BlankNode {id : _} } =>
          blank_nodes.push(triple.object()),
        _ => { }
      }
    }

    blank_nodes
  }

  /// Returns the stored triples as vector.
  pub fn into_vec(self) -> Vec<Triple> {
    self.triples
  }

  /// Returns an iterator over the stored triples.
  pub fn iter(&self) -> Iter<Triple> {
    self.triples.iter()
  }
}

impl IntoIterator for TripleStore {
  type Item = Triple;
  type IntoIter = IntoIter<Triple>;

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

#[cfg(test)]
mod tests {
  use node::*;
  use triple::*;
  use std::collections::LinkedList;

  #[test]
  fn empty_triple_store() {
    let store = TripleStore::new();

    assert!(store.is_empty());
  }

  #[test]
  fn count_triples_in_triple_store() {
    let mut store = TripleStore::new();

    let subject = Node::LiteralNode {
      literal: "abcd".to_string(),
      prefix: None,
      data_type: None,
      language: None
    };

    let predicate = Node::LiteralNode {
      literal: "d".to_string(),
      prefix: None,
      data_type: None,
      language: None
    };

    let object = Node::LiteralNode {
      literal: "s".to_string(),
      prefix: None,
      data_type: None,
      language: None
    };

    let trip = Triple::new(subject, predicate, object);

    store.add_triple(&trip);

    assert_eq!(store.count(), 1);
  }
}
<commit_msg>Add examples for triple usage<commit_after>use node::{Node};
use std::slice::Iter;
use std::vec::IntoIter;
use std::cmp::PartialEq;
use std::fmt;

/// Triple segment.
#[derive(PartialEq, Debug)]
pub enum TripleSegment {
  Subject,
  Predicate,
  Object
}

/// Triple representation.
#[derive(Clone, Debug)]
pub struct Triple {
  subject: Node,
  predicate: Node,
  object: Node
}

impl Triple {
  /// Constructor for Triple struct.
  ///
  /// Requires subject, predicate and object nodes.
  ///
  /// # Examples
  ///
  /// use rdf_sr::triple::Triple;
  /// use rdf_rs::node::Node;
  ///
  /// let subject = graph.create_blank_node();
  /// let predicate = graph.create_uri_node(&Uri::new("http://example.org/show/localName".to_string()));
  /// let object = graph.create_blank_node();
  ///
  /// let triple = Triple::new(subject, predicate, object);
  ///
  pub fn new(subject: Node, predicate: Node, object: Node) -> Triple {
    Triple {
      subject: subject.clone(),
      predicate: predicate.clone(),
      object: object.clone()
    }
  }

  /// Returns a reference to the subject node of the triple.
  pub fn subject(&self) -> &Node {
    &self.subject
  }

  /// Returns a reference to the predicate node of the triple.
  pub fn predicate(&self) -> &Node {
    &self.predicate
  }

  /// Returns a reference to the object node of the triple.
  pub fn object(&self) -> &Node {
    &self.object
  }
}

impl PartialEq for Triple {
  fn eq(&self, other: &Triple) -> bool {
    self.subject() == other.subject() &&
    self.predicate() == other.predicate() &&
    self.object() == other.object()
  }
}

impl Eq for Triple { }

/// Storage for triples.
#[derive(Debug)]
pub struct TripleStore {
  triples: Vec<Triple>
}

impl TripleStore {
  /// Constructs a new triple store.
  pub fn new() -> TripleStore {
    TripleStore {
      triples: Vec::new()
    }
  }

  /// Returns the number of triples that are stored.
  pub fn count(&self) -> usize {
    self.triples.len()
  }

  /// Checks if the triple store is empty.
  pub fn is_empty(&self) -> bool {
    self.count() == 0
  }

  /// Adds a new triple to the store.
  pub fn add_triple(&mut self, triple: &Triple) {
    self.triples.push(triple.clone());
  }

  /// Deletes the triple from the store.
  pub fn remove_triple(&mut self, triple: &Triple) {
    self.triples.retain(|ref t| {
      *t != triple
    });
  }

  /// Returns all triples where the subject node matches the provided node.
  pub fn get_triples_with_subject(&self, node: &Node) -> Vec<&Triple> {
    self.triples.iter().filter(|t| t.subject() == node).collect::<Vec<_>>()
  }

  /// Returns all triples where the predicate node matches the provided node.
  pub fn get_triples_with_predicate(&self, node: &Node) -> Vec<&Triple> {
    self.triples.iter().filter(|t| t.predicate() == node).collect::<Vec<_>>()
  }

  /// Returns all triples where the object node matches the provided node.
  pub fn get_triples_with_object(&self, node: &Node) -> Vec<&Triple> {
    self.triples.iter().filter(|t| t.object() == node).collect::<Vec<_>>()
  }

  /// Returns all triples where the subject and object nodes match the provided nodes.
  pub fn get_triples_with_subject_and_object(&self, subject_node: &Node, object_node: &Node) -> Vec<&Triple> {
    self.triples.iter().filter(|t|
      t.object() == object_node && t.subject() == subject_node
    ).collect::<Vec<_>>()
  }

  /// Returns all triples where the subject and predicate nodes match the provided nodes.
  pub fn get_triples_with_subject_and_predicate(&self, subject_node: &Node, predicate_node: &Node) -> Vec<&Triple> {
    self.triples.iter().filter(|t|
      t.predicate() == predicate_node && t.subject() == subject_node
    ).collect::<Vec<_>>()
  }

  /// Returns all triples where the predicate and object nodes match the provided nodes.
  pub fn get_triples_with_predicate_and_object(&self, predicate_node: &Node, object_node: &Node) -> Vec<&Triple> {
    self.triples.iter().filter(|t|
      t.predicate() == predicate_node && t.object() == object_node
    ).collect::<Vec<_>>()
  }

  /// Returns all blank nodes of the store.
  pub fn get_blank_nodes(&self) -> Vec<&Node> {
    let mut blank_nodes = Vec::new();

    for triple in self.triples.iter() {
      match triple {
        &Triple { subject: Node::BlankNode {id : _}, predicate: _, object: Node::BlankNode {id : _} } => {
          blank_nodes.push(triple.subject());
          blank_nodes.push(triple.object());
        },
        &Triple { subject: Node::BlankNode {id : _}, predicate: _, object: _ } =>
          blank_nodes.push(triple.subject()),
        &Triple { subject: _, predicate: _, object: Node::BlankNode {id : _} } =>
          blank_nodes.push(triple.object()),
        _ => { }
      }
    }

    blank_nodes
  }

  /// Returns the stored triples as vector.
  pub fn into_vec(self) -> Vec<Triple> {
    self.triples
  }

  /// Returns an iterator over the stored triples.
  pub fn iter(&self) -> Iter<Triple> {
    self.triples.iter()
  }
}

impl IntoIterator for TripleStore {
  type Item = Triple;
  type IntoIter = IntoIter<Triple>;

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

#[cfg(test)]
mod tests {
  use node::*;
  use triple::*;
  use std::collections::LinkedList;

  #[test]
  fn empty_triple_store() {
    let store = TripleStore::new();

    assert!(store.is_empty());
  }

  #[test]
  fn count_triples_in_triple_store() {
    let mut store = TripleStore::new();

    let subject = Node::LiteralNode {
      literal: "abcd".to_string(),
      prefix: None,
      data_type: None,
      language: None
    };

    let predicate = Node::LiteralNode {
      literal: "d".to_string(),
      prefix: None,
      data_type: None,
      language: None
    };

    let object = Node::LiteralNode {
      literal: "s".to_string(),
      prefix: None,
      data_type: None,
      language: None
    };

    let trip = Triple::new(subject, predicate, object);

    store.add_triple(&trip);

    assert_eq!(store.count(), 1);
  }
}
<|endoftext|>


<commit_before>/// Breadth First Search
pub mod bfs {

    use hex2d::Coordinate;

    use std;
    use std::hash;
    use std::num::{SignedInt, FromPrimitive};
    use num::integer::{Integer};
    use std::collections::ring_buf::RingBuf;
    use std::collections::HashMap;
    use std::collections::hash_map::Entry::{Occupied,Vacant};

    struct Visited<I = i32>
        where I : SignedInt+hash::Hash<std::collections::hash_map::Hasher> {
        prev : Coordinate<I>,
        dist : u32,
    }

    /// Breadth First Search
    ///
    /// Use BFS to find closest (in walk steps) Coordinates that satisfy `is_dest` and can be
    /// reached with a walk through coordinates for which `can_pass` returns true.
    pub struct Traverser<FCanPass, FIsDest, I = i32> where
        I : SignedInt+hash::Hash<std::collections::hash_map::Hasher>,
        FCanPass : Fn(Coordinate<I>) -> bool,
        FIsDest : Fn(Coordinate<I>) -> bool
    {
        visited : HashMap<Coordinate<I>, Visited<I>>,
        to_traverse : RingBuf<Coordinate<I>>,
        can_pass : FCanPass,
        is_dest : FIsDest,
        start : Coordinate<I>,
    }

    impl<FCanPass, FIsDest, I> Traverser<FCanPass, FIsDest, I> where
        I : SignedInt+FromPrimitive+Integer+hash::Hash<std::collections::hash_map::Hasher>,
        FCanPass : Fn(Coordinate<I>) -> bool,
        FIsDest : Fn(Coordinate<I>) -> bool
    {

        /// Create a Traverser instance with initial conditions
        pub fn new(can_pass : FCanPass, is_dest : FIsDest, start: Coordinate<I>) -> Traverser<FCanPass, FIsDest, I> {
            let mut to_traverse = RingBuf::new();
            to_traverse.push_back(start);

            let mut visited = HashMap::new();
            visited.insert(start, Visited{prev: start, dist: 0});

            Traverser {
                visited: visited,
                to_traverse: to_traverse,
                can_pass: can_pass,
                is_dest: is_dest,
                start: start,
            }
        }

        /// Find next closest coordinate.
        ///
        /// Can be called multiple times, each time returning next coordinate
        pub fn find(&mut self) -> Option<Coordinate<I>> {

            loop {
                let pos = match self.to_traverse.pop_front() {
                    None => return None,
                    Some(coord) => coord,
                };

                // Traverse before returning, so `find` can be call subsequently
                // for more than just first answer
                if (self.can_pass)(pos) {

                    let &Visited{dist, ..} = self.visited.get(&pos).expect("BFS: Should have been visited already");

                    let dist = dist + 1;

                    for &npos in pos.neighbors().iter() {
                        match self.visited.entry(npos) {
                            Occupied(_) => { /* already visited */ }
                            Vacant(entry) => {
                                entry.insert(Visited{prev: pos, dist: dist});
                                self.to_traverse.push_back(npos);
                            }
                        }
                    }
                }

                if (self.is_dest)(pos) {
                    return Some(pos);
                }
            }
        }

        /// Return neighbor Coordinate to `pos` that is one step closer to
        /// `start` from initial conditions.
        ///
        /// Useful for finding whole path to a Coordinate returned by `find`.
        ///
        /// Returns `None` for Coordinates that were not yet visited.
        /// Returns `start` for `start` (from initial conditions)
        pub fn backtrace(&self, pos : Coordinate<I>) -> Option<Coordinate<I>> {
            self.visited.get(&pos).map(|entry| entry.prev)
        }

        /// Perform a recursive `backtrace` walk to find a neighbor of `start` that leads to the
        /// Coordinate returned by `find()`.
        ///
        /// Returns `None` for Coordinates that were not yet visited.
        /// Returns `start` for `start` (from initial conditions)
        pub fn backtrace_last(&self, mut pos : Coordinate<I>) -> Option<Coordinate<I>> {
            loop {
                pos = match self.visited.get(&pos) {
                    None => return None,
                    Some(entry) => {
                        if entry.prev == self.start {
                            return Some(pos);
                        } else {
                            entry.prev
                        }
                    }
                }
            }
        }
    }
}

/// Very tricky, but (hopefully) good enough, recursive LoS algorithm
pub mod los {
    use hex2d::Angle::{Left,Right};
    use hex2d::Direction;
    use hex2d::Coordinate;
    use std::num::{SignedInt, FromPrimitive};
    use num::integer::{Integer};

    fn los_rec<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        p : Coordinate<I>,
        main_dir : Direction,
        dir : Option<Direction>,
        pdir : Option<Direction>,
    ) where
        I : SignedInt+FromPrimitive+Integer,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>)
        {
            visible(p);

            let mut light = light;
            let opaq = opaqueness(p);

            if opaq >= light {
                return;
            } else {
                light = light - opaq;
            }

            let neighbors = match (dir, pdir) {
                (Some(dir), Some(pdir)) => {

                    if main_dir == dir {
                        visible(p + (main_dir + Right));
                        visible(p + (main_dir + Left));
                    }

                    if dir == pdir {
                        vec!(dir)
                    } else {
                        vec!(dir, pdir)
                    }
                },
                (Some(dir), None) => {
                    if main_dir == dir {
                        visible(p + (main_dir + Right));
                        visible(p + (main_dir + Left));
                        vec!(dir, dir + Left, dir + Right)
                    } else {
                        visible((p + main_dir));
                        vec!(dir, main_dir)
                    }
                },
                _ => {
                    visible(p + main_dir);
                    visible(p + (main_dir + Left));
                    visible(p + (main_dir + Right));
                    vec!(main_dir, main_dir + Left, main_dir + Right)
                }
            };

            for &d in neighbors.iter() {
                let n = p + d;
                match dir {
                    Some(_) => los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, n, d, Some(d), dir),
                    None => los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, n, main_dir, Some(d), dir),
                }
            }
        }

    /// Starting from `pos` in direction `dir`, call `visible` for each visible Coordinate.
    ///
    /// Use `light` as starting range of the LoS. For each visible Coordinate, the value returned
    /// by `opaqueness` will be subtracted from `light` to check if the LoS should finish due to
    /// "lack of visibility". `opaqueness` should typically return 1 for fully transparent
    /// Coordinates, and anything bigger than initial `light` for fully opaque Coordinates.
    pub fn los<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        pos : Coordinate<I>,
        dirs : &[Direction],
    ) where
        I : SignedInt+FromPrimitive+Integer,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>)
        {
            for dir in dirs.iter() {
                los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, pos, *dir, None, None);
            }
        }
}
<commit_msg>Pass light argument on `visit` in LoS.<commit_after>/// Breadth First Search
pub mod bfs {

    use hex2d::Coordinate;

    use std;
    use std::hash;
    use std::num::{SignedInt, FromPrimitive};
    use num::integer::{Integer};
    use std::collections::ring_buf::RingBuf;
    use std::collections::HashMap;
    use std::collections::hash_map::Entry::{Occupied,Vacant};

    struct Visited<I = i32>
        where I : SignedInt+hash::Hash<std::collections::hash_map::Hasher> {
        prev : Coordinate<I>,
        dist : u32,
    }

    /// Breadth First Search
    ///
    /// Use BFS to find closest (in walk steps) Coordinates that satisfy `is_dest` and can be
    /// reached with a walk through coordinates for which `can_pass` returns true.
    pub struct Traverser<FCanPass, FIsDest, I = i32> where
        I : SignedInt+hash::Hash<std::collections::hash_map::Hasher>,
        FCanPass : Fn(Coordinate<I>) -> bool,
        FIsDest : Fn(Coordinate<I>) -> bool
    {
        visited : HashMap<Coordinate<I>, Visited<I>>,
        to_traverse : RingBuf<Coordinate<I>>,
        can_pass : FCanPass,
        is_dest : FIsDest,
        start : Coordinate<I>,
    }

    impl<FCanPass, FIsDest, I> Traverser<FCanPass, FIsDest, I> where
        I : SignedInt+FromPrimitive+Integer+hash::Hash<std::collections::hash_map::Hasher>,
        FCanPass : Fn(Coordinate<I>) -> bool,
        FIsDest : Fn(Coordinate<I>) -> bool
    {

        /// Create a Traverser instance with initial conditions
        pub fn new(can_pass : FCanPass, is_dest : FIsDest, start: Coordinate<I>) -> Traverser<FCanPass, FIsDest, I> {
            let mut to_traverse = RingBuf::new();
            to_traverse.push_back(start);

            let mut visited = HashMap::new();
            visited.insert(start, Visited{prev: start, dist: 0});

            Traverser {
                visited: visited,
                to_traverse: to_traverse,
                can_pass: can_pass,
                is_dest: is_dest,
                start: start,
            }
        }

        /// Find next closest coordinate.
        ///
        /// Can be called multiple times, each time returning next coordinate
        pub fn find(&mut self) -> Option<Coordinate<I>> {

            loop {
                let pos = match self.to_traverse.pop_front() {
                    None => return None,
                    Some(coord) => coord,
                };

                // Traverse before returning, so `find` can be call subsequently
                // for more than just first answer
                if (self.can_pass)(pos) {

                    let &Visited{dist, ..} = self.visited.get(&pos).expect("BFS: Should have been visited already");

                    let dist = dist + 1;

                    for &npos in pos.neighbors().iter() {
                        match self.visited.entry(npos) {
                            Occupied(_) => { /* already visited */ }
                            Vacant(entry) => {
                                entry.insert(Visited{prev: pos, dist: dist});
                                self.to_traverse.push_back(npos);
                            }
                        }
                    }
                }

                if (self.is_dest)(pos) {
                    return Some(pos);
                }
            }
        }

        /// Return neighbor Coordinate to `pos` that is one step closer to
        /// `start` from initial conditions.
        ///
        /// Useful for finding whole path to a Coordinate returned by `find`.
        ///
        /// Returns `None` for Coordinates that were not yet visited.
        /// Returns `start` for `start` (from initial conditions)
        pub fn backtrace(&self, pos : Coordinate<I>) -> Option<Coordinate<I>> {
            self.visited.get(&pos).map(|entry| entry.prev)
        }

        /// Perform a recursive `backtrace` walk to find a neighbor of `start` that leads to the
        /// Coordinate returned by `find()`.
        ///
        /// Returns `None` for Coordinates that were not yet visited.
        /// Returns `start` for `start` (from initial conditions)
        pub fn backtrace_last(&self, mut pos : Coordinate<I>) -> Option<Coordinate<I>> {
            loop {
                pos = match self.visited.get(&pos) {
                    None => return None,
                    Some(entry) => {
                        if entry.prev == self.start {
                            return Some(pos);
                        } else {
                            entry.prev
                        }
                    }
                }
            }
        }
    }
}

/// Very tricky, but (hopefully) good enough, recursive LoS algorithm
pub mod los {
    use hex2d::Angle::{Left,Right};
    use hex2d::Direction;
    use hex2d::Coordinate;
    use std::num::{SignedInt, FromPrimitive};
    use num::integer::{Integer};

    fn los_rec<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        p : Coordinate<I>,
        main_dir : Direction,
        dir : Option<Direction>,
        pdir : Option<Direction>,
    ) where
        I : SignedInt+FromPrimitive+Integer,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {
            visible(p, light);

            let mut light = light;
            let opaq = opaqueness(p);

            if opaq >= light {
                return;
            } else {
                light = light - opaq;
            }

            let neighbors = match (dir, pdir) {
                (Some(dir), Some(pdir)) => {

                    if main_dir == dir {
                        visible(p + (main_dir + Right), light);
                        visible(p + (main_dir + Left), light);
                    }

                    if dir == pdir {
                        vec!(dir)
                    } else {
                        vec!(dir, pdir)
                    }
                },
                (Some(dir), None) => {
                    if main_dir == dir {
                        visible(p + (main_dir + Right), light);
                        visible(p + (main_dir + Left), light);
                        vec!(dir, dir + Left, dir + Right)
                    } else {
                        visible((p + main_dir), light);
                        vec!(dir, main_dir)
                    }
                },
                _ => {
                    visible(p + main_dir, light);
                    visible(p + (main_dir + Left), light);
                    visible(p + (main_dir + Right), light);
                    vec!(main_dir, main_dir + Left, main_dir + Right)
                }
            };

            for &d in neighbors.iter() {
                let n = p + d;
                match dir {
                    Some(_) => los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, n, d, Some(d), dir),
                    None => los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, n, main_dir, Some(d), dir),
                }
            }
        }

    /// Starting from `pos` in direction `dir`, call `visible` for each visible Coordinate.
    ///
    /// Use `light` as starting range of the LoS. For each visible Coordinate, the value returned
    /// by `opaqueness` will be subtracted from `light` to check if the LoS should finish due to
    /// "lack of visibility". `opaqueness` should typically return 1 for fully transparent
    /// Coordinates, and anything bigger than initial `light` for fully opaque Coordinates.
    pub fn los<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        pos : Coordinate<I>,
        dirs : &[Direction],
    ) where
        I : SignedInt+FromPrimitive+Integer,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {
            for dir in dirs.iter() {
                los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, pos, *dir, None, None);
            }
        }
}
<|endoftext|>


<commit_before>//
// Created by Eugene Cherkasov on 03.09.2016.
// Copyright (c) 2014-2016 stage team. All rights reserved.
//

//! Math vector with basic operations
//! For now implemented for 2-dimensional space only.

use std::ops::{Add, Sub, Mul};
use Number;

#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub struct Vector2<T: Number> {
    pub x: T,
    pub y: T,
}

impl<T> Add for Vector2<T> where T: Number, <T as Add>::Output: Number {
    type Output = Vector2<<T as Add>::Output>;

    fn add(self, rhs: Vector2<T>) -> Vector2<<T as Add>::Output> {
        Vector2 { x: self.x + rhs.x, y: self.y + rhs.y }
    }
}

impl<T> Sub for Vector2<T> where T: Number, <T as Sub>::Output: Number {
    type Output = Vector2<<T as Sub>::Output>;

    fn sub(self, rhs: Vector2<T>) -> Vector2<<T as Sub>::Output> {
        Vector2 { x: self.x - rhs.x, y: self.y - rhs.y }
    }
}

impl<T> Mul<T> for Vector2<T> where T: Number, <T as Mul>::Output: Number {
    type Output = Vector2<<T as Mul>::Output>;

    fn mul(self, rhs: T) -> Vector2<<T as Mul>::Output> {
        Vector2 { x: self.x * rhs, y: self.y * rhs }
    }
}

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

    const VECTOR_1: Vector2<f32> = Vector2 { x: 10.0, y: 20.0 };
    const VECTOR_2: Vector2<f32> = Vector2 { x: 20.0, y: 20.0 };

    const SCALE: f32 = 2.0;

    #[test]
    fn test_equal() {
        let vec = VECTOR_1;
        assert_eq!( VECTOR_1 == VECTOR_2, false );
        assert_eq!( VECTOR_1 == vec, true );
    }

    #[test]
    fn test_ops() {
        let v_add = Vector2 { x: VECTOR_1.x + VECTOR_2.x, y: VECTOR_1.y + VECTOR_2.y };
        let v_sub = Vector2 { x: VECTOR_1.x - VECTOR_2.x, y: VECTOR_1.y - VECTOR_2.y };
        let v_mul = Vector2 { x: VECTOR_1.x * SCALE, y: VECTOR_1.y * SCALE };
        assert_eq!(v_add, VECTOR_1 + VECTOR_2);
        assert_eq!(v_sub, VECTOR_1 - VECTOR_2);
        assert_eq!(v_mul, VECTOR_1 * SCALE);
    }
}
<commit_msg>Add magnitude for Vector.<commit_after>//
// Created by Eugene Cherkasov on 03.09.2016.
// Copyright (c) 2014-2016 stage team. All rights reserved.
//

//! Math vector with basic operations
//! For now implemented for 2-dimensional space only.

use std::ops::{Add, Sub, Mul};
use Number;

#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub struct Vector2<T: Number> {
    pub x: T,
    pub y: T,
}

impl<T> Add for Vector2<T> where T: Number, <T as Add>::Output: Number {
    type Output = Vector2<<T as Add>::Output>;

    fn add(self, rhs: Vector2<T>) -> Vector2<<T as Add>::Output> {
        Vector2 { x: self.x + rhs.x, y: self.y + rhs.y }
    }
}

impl<T> Sub for Vector2<T> where T: Number, <T as Sub>::Output: Number {
    type Output = Vector2<<T as Sub>::Output>;

    fn sub(self, rhs: Vector2<T>) -> Vector2<<T as Sub>::Output> {
        Vector2 { x: self.x - rhs.x, y: self.y - rhs.y }
    }
}

impl<T> Mul<T> for Vector2<T> where T: Number, <T as Mul>::Output: Number {
    type Output = Vector2<<T as Mul>::Output>;

    fn mul(self, rhs: T) -> Vector2<<T as Mul>::Output> {
        Vector2 { x: self.x * rhs, y: self.y * rhs }
    }
}

impl<T> Vector2<T> where T: Number {
    fn magnitude(self) -> f32 {
        let sum: f32 = self.x * self.x + self.y * self.y;
        sum.sqrt()
    }
}

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

    const VECTOR_1: Vector2<f32> = Vector2 { x: 10.0, y: 20.0 };
    const VECTOR_2: Vector2<f32> = Vector2 { x: 20.0, y: 20.0 };

    const SCALE: f32 = 2.0;

    #[test]
    fn test_equal() {
        let vec = VECTOR_1;
        assert_eq!( VECTOR_1 == VECTOR_2, false );
        assert_eq!( VECTOR_1 == vec, true );
    }

    #[test]
    fn test_ops() {
        let v_add = Vector2 { x: VECTOR_1.x + VECTOR_2.x, y: VECTOR_1.y + VECTOR_2.y };
        let v_sub = Vector2 { x: VECTOR_1.x - VECTOR_2.x, y: VECTOR_1.y - VECTOR_2.y };
        let v_mul = Vector2 { x: VECTOR_1.x * SCALE, y: VECTOR_1.y * SCALE };
        assert_eq!(v_add, VECTOR_1 + VECTOR_2);
        assert_eq!(v_sub, VECTOR_1 - VECTOR_2);
        assert_eq!(v_mul, VECTOR_1 * SCALE);
    }

    #[test]
    fn test_magnitude() {
        const MAGNITUDE: f32 = (500.0_f32).sqrt();

        assert_eq!(MAGNITUDE, VECTOR_1.magnitude());
    }
}
<|endoftext|>


<commit_before>
use glium;
use super::{Frame, Event, LoadImageError};
use image::Image;
use glium::glutin;
use std::path;
use std::time::Instant;
use support::{self, as_sec};
use events;
use img;

/**
Represets a window with OpenGL context.

This window provides image loading, rendering via `Window::next_frame(...)`,
and events via `Window::poll_events(...)`.

# Example
```rust,no_run
extern crate love2d;
use love2d::{Window, Event};

fn main() {
    let mut app = Window::new("Hello World", 640, 480);

    loop {
        // Note rust requires this code to be in a closure to please the borrow checker
        {
            let mut frame = app.next_frame();

            // Render Code Goes Here

            frame.finish();
        }

        for ev in app.poll_events() {
            match ev {
                Event::Closed => break,
                _ => (),
            }
        }
    }
}
```
*/
pub struct Window {
    display: glium::Display,
    events_loop: glium::glutin::EventsLoop,
    programs: (glium::Program, glium::Program),
    last: Instant,
}

impl Window {
    /// Create a new Window with a Title, and size (width / height) specified in
    /// pixels.
    ///
    /// # Pacnic
    /// This method will panic if there are any issues with creating the window
    /// or compiling the shaders. See the glium library for more specifics on
    /// window creation.
    ///
    /// # Example
    /// ```rust,no_run
    /// extern crate love2d;
	/// # fn main() {
    /// use love2d::Window;
    ///
    /// let mut app = Window::new("Hello World", 640, 480);
	/// # }
    /// ```
    pub fn new(title: &str, width: u32, height: u32) -> Self {
        let events_loop = glutin::EventsLoop::new();
        let window = glutin::WindowBuilder::new()
            .with_title(title)
            .with_dimensions(width, height);
        let context = glutin::ContextBuilder::new();
        let display =
            glium::Display::new(window, context, &events_loop).expect("Could not create Display");
        let color_program =
            support::shaders::color::load_program(&display).expect("Could not create color shader");
        let texture_program = support::shaders::texture::load_program(&display)
            .expect("Could not create texture shader");

        Window {
            display: display,
            events_loop: events_loop,
            programs: (color_program, texture_program),
            last: Instant::now(),
        }
    }

    /// Load an image from a file to be drawn by `Frame::draw_image(...)`.
    ///
    /// # Parameters
    ///
    /// * `path` - a path pointing to an image file
    ///
    /// # Example
    /// ```rust,no_run
    /// # extern crate love2d;
	/// # fn main() {
    /// # use love2d::Window;
    /// let mut app = Window::new("Hello World", 640, 480);
    /// let pic = app.load_image("res/city.jpg");
	/// # }
    /// ```
    pub fn load_image<'a, P: AsRef<path::Path>>(&self, path: P) -> Result<Image, LoadImageError> {
        use std::io::prelude::*;
        use std::fs::File;

        let mut buf = Vec::new();
        match File::open(path) {
            Ok(mut file) => {
                match file.read_to_end(&mut buf) {
                    Ok(_) => (),
                    Err(err) => return Err(LoadImageError::FileError(err)),
                }
            }
            Err(err) => return Err(LoadImageError::FileError(err)),
        }

        match img::load_from_memory(&buf[..]) {
            Ok(image) => {
                let image = image.to_rgba();
                let image_dimensions = image.dimensions();
                let glimage =
                    glium::texture::RawImage2d::from_raw_rgba(image.into_raw(), image_dimensions);
                let texture = glium::texture::Texture2d::new(&self.display, glimage).unwrap();

                return Ok(Image::new(image_dimensions, texture));
            }
            Err(err) => return Err(LoadImageError::ImageError(err)),
        }
    }

    /// Poll the window for events.
    ///
    /// # Example
    /// ```rust,no_run
    /// # extern crate love2d;
    /// # use love2d::Window;
	/// # fn main() {
    /// use love2d::Event;
    ///
    /// let mut app = Window::new("Hello World", 640, 480);
    ///
    /// for ev in app.poll_events() {
    ///     match ev {
    ///         _ => ()
    ///     }
    /// }
	/// # }
    /// ```
    pub fn poll_events(&mut self) -> Vec<Event> {
        let mut events: Vec<Event> = Vec::new();

        self.events_loop.poll_events(|ev| {
            let event = events::translate(ev);
            match event {
                Event::Unsupported => (),
                event => events.push(event),
            }
        });

        events
    }

    /// Get the next frame for rendering.
    ///
    /// This method sets up the window and renderer for the next frame. The
    /// `Frame` object returned includes the methods for rendering to the frame
    /// along with delta time and window size.
    ///
    /// # Example
    /// ```rust,no_run
    /// # extern crate love2d;
    /// # use love2d::Window;
	/// # fn main() {
    /// let mut app = Window::new("Hello World", 640, 480);
    ///
    /// loop {
    ///     let mut frame = app.next_frame();
    ///
    ///     // Render code goes here
    ///
    ///     frame.finish();
    /// }
	/// # }
    /// ```
    pub fn next_frame(&mut self) -> Frame {
        let curr = Instant::now();
        let delta = as_sec(curr - self.last);
        self.last = curr;

        Frame::new(&self.display, &self.programs, delta)
    }
}
<commit_msg>Made Window::new title an Into<String><commit_after>
use glium;
use super::{Frame, Event, LoadImageError};
use image::Image;
use glium::glutin;
use std::path;
use std::time::Instant;
use support::{self, as_sec};
use events;
use img;

/**
Represets a window with OpenGL context.

This window provides image loading, rendering via `Window::next_frame(...)`,
and events via `Window::poll_events(...)`.

# Example
```rust,no_run
extern crate love2d;
use love2d::{Window, Event};

fn main() {
    let mut app = Window::new("Hello World", 640, 480);

    loop {
        // Note rust requires this code to be in a closure to please the borrow checker
        {
            let mut frame = app.next_frame();

            // Render Code Goes Here

            frame.finish();
        }

        for ev in app.poll_events() {
            match ev {
                Event::Closed => break,
                _ => (),
            }
        }
    }
}
```
*/
pub struct Window {
    display: glium::Display,
    events_loop: glium::glutin::EventsLoop,
    programs: (glium::Program, glium::Program),
    last: Instant,
}

impl Window {
    /// Create a new Window with a Title, and size (width / height) specified in
    /// pixels.
    ///
    /// # Pacnic
    /// This method will panic if there are any issues with creating the window
    /// or compiling the shaders. See the glium library for more specifics on
    /// window creation.
    ///
    /// # Example
    /// ```rust,no_run
    /// extern crate love2d;
	/// # fn main() {
    /// use love2d::Window;
    ///
    /// let mut app = Window::new("Hello World", 640, 480);
	/// # }
    /// ```
    pub fn new<S: Into<String>>(title: S, width: u32, height: u32) -> Self {
        let events_loop = glutin::EventsLoop::new();
        let window = glutin::WindowBuilder::new()
            .with_title(title)
            .with_dimensions(width, height);
        let context = glutin::ContextBuilder::new();
        let display =
            glium::Display::new(window, context, &events_loop).expect("Could not create Display");
        let color_program =
            support::shaders::color::load_program(&display).expect("Could not create color shader");
        let texture_program = support::shaders::texture::load_program(&display)
            .expect("Could not create texture shader");

        Window {
            display: display,
            events_loop: events_loop,
            programs: (color_program, texture_program),
            last: Instant::now(),
        }
    }

    /// Load an image from a file to be drawn by `Frame::draw_image(...)`.
    ///
    /// # Parameters
    ///
    /// * `path` - a path pointing to an image file
    ///
    /// # Example
    /// ```rust,no_run
    /// # extern crate love2d;
	/// # fn main() {
    /// # use love2d::Window;
    /// let mut app = Window::new("Hello World", 640, 480);
    /// let pic = app.load_image("res/city.jpg");
	/// # }
    /// ```
    pub fn load_image<'a, P: AsRef<path::Path>>(&self, path: P) -> Result<Image, LoadImageError> {
        use std::io::prelude::*;
        use std::fs::File;

        let mut buf = Vec::new();
        match File::open(path) {
            Ok(mut file) => {
                match file.read_to_end(&mut buf) {
                    Ok(_) => (),
                    Err(err) => return Err(LoadImageError::FileError(err)),
                }
            }
            Err(err) => return Err(LoadImageError::FileError(err)),
        }

        match img::load_from_memory(&buf[..]) {
            Ok(image) => {
                let image = image.to_rgba();
                let image_dimensions = image.dimensions();
                let glimage =
                    glium::texture::RawImage2d::from_raw_rgba(image.into_raw(), image_dimensions);
                let texture = glium::texture::Texture2d::new(&self.display, glimage).unwrap();

                return Ok(Image::new(image_dimensions, texture));
            }
            Err(err) => return Err(LoadImageError::ImageError(err)),
        }
    }

    /// Poll the window for events.
    ///
    /// # Example
    /// ```rust,no_run
    /// # extern crate love2d;
    /// # use love2d::Window;
	/// # fn main() {
    /// use love2d::Event;
    ///
    /// let mut app = Window::new("Hello World", 640, 480);
    ///
    /// for ev in app.poll_events() {
    ///     match ev {
    ///         _ => ()
    ///     }
    /// }
	/// # }
    /// ```
    pub fn poll_events(&mut self) -> Vec<Event> {
        let mut events: Vec<Event> = Vec::new();

        self.events_loop.poll_events(|ev| {
            let event = events::translate(ev);
            match event {
                Event::Unsupported => (),
                event => events.push(event),
            }
        });

        events
    }

    /// Get the next frame for rendering.
    ///
    /// This method sets up the window and renderer for the next frame. The
    /// `Frame` object returned includes the methods for rendering to the frame
    /// along with delta time and window size.
    ///
    /// # Example
    /// ```rust,no_run
    /// # extern crate love2d;
    /// # use love2d::Window;
	/// # fn main() {
    /// let mut app = Window::new("Hello World", 640, 480);
    ///
    /// loop {
    ///     let mut frame = app.next_frame();
    ///
    ///     // Render code goes here
    ///
    ///     frame.finish();
    /// }
	/// # }
    /// ```
    pub fn next_frame(&mut self) -> Frame {
        let curr = Instant::now();
        let delta = as_sec(curr - self.last);
        self.last = curr;

        Frame::new(&self.display, &self.programs, delta)
    }
}
<|endoftext|>


<commit_before>pub trait Cell {
    fn step<C: Cell>(&self, neighbors: &[C]);
}<commit_msg>Final trait signature.<commit_after>pub trait Cell {
    fn step<'a, I>(&'a self, neighbors: I) -> Self
        where I: Iterator<Item=Option<&'a Self>>;
}<|endoftext|>


<commit_before>#![cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]

use std::iter;
use environment::*;
use types::*;
use types::RispType::*;

fn sum(list: Vec<RispType>) -> RispResult {
    let mut s = 0;
    for x in list {
        match x {
            Int(x2) => { s += x2 }
            _ => return error_result("I want ints!")
        }
    }
    Ok(Int(s))
}

fn mul(list: Vec<RispType>) -> RispResult {
    let mut s = 1;
    for x in list {
        match x {
            Int(x2) => { s *= x2 }
            _ => return error_result("I want ints!")
        }
    }
    Ok(Int(s))
}

fn rep(args: Vec<RispType>) -> RispResult {
    if let Some((n, elements)) = args.split_first() {
        match *n {
            Int(n2) => {
                Ok(Vector(repeated(elements, n2 as usize)))
            }
            _ => error_result("rep needs an int as first argument")
        }
    } else {
        error_result("rep needs 2 arguments but got 0")
    }
}

fn repeated<T: Clone>(pattern: &[T], times: usize) -> Vec<T> {
    concat(iter::repeat(pattern.to_vec()).take(times).collect())
}

fn concat<T: Clone>(input: Vec<Vec<T>>) -> Vec<T> {
    input.into_iter().flat_map(|x| x).collect()
}

pub fn create_core_environment() -> Environment {
    let mut env = Environment::new();
    env.set("+", Function(sum));
    env.set("*", Function(mul));
    env.set("rep", Function(rep));
    env
}

/* ------------------------------ Tests ----------------------------------------------- */

#[test]
fn test_sum_errors() {
    assert!(sum(vec![List(vec![])]).is_err());
}

#[test]
fn test_mul_errors() {
    assert!(mul(vec![List(vec![])]).is_err());
}

#[test]
fn test_rep() {
    assert_eq!(
    rep(vec![Int(2), Int(3), Int(4)]),
    Ok(Vector(vec![Int(3), Int(4), Int(3), Int(4)]))
    );
}

#[test]
fn test_rep_nested() {
    assert_eq!(
    rep(vec![Int(2), Vector(vec![Int(3), Int(4)])]),
    Ok(Vector(vec![Vector(vec![Int(3), Int(4)]), Vector(vec![Int(3), Int(4)])]))
    );
}

#[test]
fn test_rep_missing_arguments() {
    assert_eq!(rep(vec![]), error_result("rep needs 2 arguments but got 0"));
}

#[test]
fn test_rep_needs_int_as_first_argument() {
    assert_eq!(rep(vec![string("23")]), error_result("rep needs an int as first argument"));
}<commit_msg>Addition of vectors<commit_after>#![cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]

use std::iter;
use environment::*;
use types::*;
use types::RispType::*;
use std::cmp;

fn sum(list: Vec<RispType>) -> RispResult {
    list.iter().fold(Ok(Int(0)), |acc, x| sum2(&acc?, x))
}

fn sum2(x1: &RispType, x2: &RispType) -> RispResult {
    match *x1 {
        Int(x1_int) => match *x2 {
            Int(x2_int) => Ok(Int(x1_int + x2_int)),
            Vector(ref x2_vec) => add_number_to_vector(x1_int, x2_vec),
            _ => error_result(format!("Sum wants an Int or a Vector as second argument but got {:?}", x2))
        },
        Vector(ref x1_vec) => match *x2 {
            Int(x2_int) => add_number_to_vector(x2_int, x1_vec),
            Vector(ref x2_vec) => add_vector_to_vector(x1_vec, x2_vec),
            _ => error_result(format!("Sum wants an Int or a Vector as second argument but got {:?}", x2))
        },
        _ => error_result(format!("Sum wants an Int or a Vector as first argument but got {:?}", x1))
    }
}

fn add_number_to_vector(x_int: i64, xs: &Vec<RispType>) -> RispResult {
    let x = Int(x_int);
    xs.iter().map(|x2| sum2(&x, x2))
        .collect::<Result<_, _>>()
        .map(Vector)
}

fn add_vector_to_vector(xs1: &Vec<RispType>, xs2: &Vec<RispType>) -> RispResult {
    let result_len = cmp::max(xs1.len(), xs2.len());
    (0..result_len)
        .map(|i| sum2(&xs1[i % xs1.len()], &xs2[i % xs2.len()]))
        .collect::<Result<_, _>>()
        .map(Vector)
}

fn mul(list: Vec<RispType>) -> RispResult {
    let mut s = 1;
    for x in list {
        match x {
            Int(x2) => { s *= x2 }
            _ => return error_result("I want ints!")
        }
    }
    Ok(Int(s))
}

fn rep(args: Vec<RispType>) -> RispResult {
    if let Some((n, elements)) = args.split_first() {
        match *n {
            Int(n2) => {
                Ok(Vector(repeated(elements, n2 as usize)))
            }
            _ => error_result("rep needs an int as first argument")
        }
    } else {
        error_result("rep needs 2 arguments but got 0")
    }
}

fn repeated<T: Clone>(pattern: &[T], times: usize) -> Vec<T> {
    concat(iter::repeat(pattern.to_vec()).take(times).collect())
}

fn concat<T: Clone>(input: Vec<Vec<T>>) -> Vec<T> {
    input.into_iter().flat_map(|x| x).collect()
}

pub fn create_core_environment() -> Environment {
    let mut env = Environment::new();
    env.set("+", Function(sum));
    env.set("*", Function(mul));
    env.set("rep", Function(rep));
    env
}

/* ------------------------------ Tests ----------------------------------------------- */

#[test]
fn test_sum() {
    assert_eq!(sum(vec![Int(1), Int(2)]), Ok(Int(3)));
}

#[test]
fn test_sum_number_vector() {
    assert_eq!(sum(vec![Int(20), Vector(vec![Int(1), Int(2)])]), Ok(Vector(vec![Int(21), Int(22)])));
}

#[test]
fn test_sum_number_vector_vector() {
    assert_eq!(sum(vec![Int(20), Vector(vec![Int(1), Int(2)]), Vector(vec![Int(100), Int(200)])]), Ok(Vector(vec![Int(121), Int(222)])));
}

#[test]
fn test_sum_number_nested_vector() {
    assert_eq!(sum(vec![
        Int(20),
        Vector(vec![Int(1), Int(2), Vector(vec![Int(100), Int(200)])]),
    ])
    , Ok(Vector(vec![Int(21), Int(22), Vector(vec![Int(120), Int(220)])])));
}

#[test]
fn test_sum2_number_vector() {
    assert_eq!(sum2(&Int(20), &Vector(vec![Int(1), Int(2)])), Ok(Vector(vec![Int(21), Int(22)])));
}

#[test]
fn test_sum2_vector_number() {
    assert_eq!(sum2(&Vector(vec![Int(1), Int(2)]), &Int(20)), Ok(Vector(vec![Int(21), Int(22)])));
}

#[test]
fn test_sum2_vector_vector() {
    assert_eq!(sum2(
        &Vector(vec![Int(1), Int(2)]),
        &Vector(vec![Int(10), Int(20)])
    ), Ok(Vector(vec![Int(11), Int(22)])));
}

#[test]
fn test_sum2_vector_longer_vector() {
    assert_eq!(sum2(
        &Vector(vec![Int(1), Int(2)]),
        &Vector(vec![Int(10), Int(20), Int(30)])
    ), Ok(Vector(vec![Int(11), Int(22), Int(31)])));
}

#[test]
fn test_sum2_errors() {
    assert_eq!(sum2(&string("string"), &Int(1)), error_result("Sum wants an Int or a Vector as first argument but got Str(\"string\")"));
    assert_eq!(sum2(&Int(1), &string("string")), error_result("Sum wants an Int or a Vector as second argument but got Str(\"string\")"));
    assert_eq!(sum2(&Vector(vec![Int(1)]), &string("string")), error_result("Sum wants an Int or a Vector as second argument but got Str(\"string\")"));
}

#[test]
fn test_add_number_to_vector() {
    assert_eq!(add_number_to_vector(20, &vec![Int(1), Int(2)]), Ok(Vector(vec![Int(21), Int(22)])));
}

#[test]
fn test_sum_errors() {
    assert!(sum(vec![Nil]).is_err());
}

#[test]
fn test_mul_errors() {
    assert!(mul(vec![List(vec![])]).is_err());
}

#[test]
fn test_rep() {
    assert_eq!(
    rep(vec![Int(2), Int(3), Int(4)]),
    Ok(Vector(vec![Int(3), Int(4), Int(3), Int(4)]))
    );
}

#[test]
fn test_rep_nested() {
    assert_eq!(
    rep(vec![Int(2), Vector(vec![Int(3), Int(4)])]),
    Ok(Vector(vec![Vector(vec![Int(3), Int(4)]), Vector(vec![Int(3), Int(4)])]))
    );
}

#[test]
fn test_rep_missing_arguments() {
    assert_eq!(rep(vec![]), error_result("rep needs 2 arguments but got 0"));
}

#[test]
fn test_rep_needs_int_as_first_argument() {
    assert_eq!(rep(vec![string("23")]), error_result("rep needs an int as first argument"));
}<|endoftext|>