<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<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.
  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<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.
  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 is_start    = true;
    let mut is_error    = false;
    let mut stream_info = StreamInfo::new();
    let mut metadata    = Vec::new();

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

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

          if is_last {
            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;
      let mut output  = Vec::with_capacity(output_size);

      unsafe { output.set_len(output_size) }

      Ok(Stream {
        info: stream_info,
        metadata: metadata,
        frames: Vec::new(),
        state: ParserState::Marker,
        output: output,
        frame_index: 0,
        producer: producer,
      })
    } 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<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);

          self.frame_index += 1;

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

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

  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<commit_msg>Remove all no longer needed handle functions<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<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.
  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<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.
  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 is_start    = true;
    let mut is_error    = false;
    let mut stream_info = StreamInfo::new();
    let mut metadata    = Vec::new();

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

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

          if is_last {
            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;
      let mut output  = Vec::with_capacity(output_size);

      unsafe { output.set_len(output_size) }

      Ok(Stream {
        info: stream_info,
        metadata: metadata,
        frames: Vec::new(),
        state: ParserState::Marker,
        output: output,
        frame_index: 0,
        producer: producer,
      })
    } 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<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);

          self.frame_index += 1;

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

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


<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<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.
  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<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.
  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 is_start    = true;
    let mut is_error    = false;
    let mut stream_info = StreamInfo::new();
    let mut metadata    = Vec::new();

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

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

          if is_last {
            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;
      let mut output  = Vec::with_capacity(output_size);

      unsafe { output.set_len(output_size) }

      Ok(Stream {
        info: stream_info,
        metadata: metadata,
        frames: Vec::new(),
        state: ParserState::Marker,
        output: output,
        frame_index: 0,
        producer: producer,
      })
    } 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<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);

          self.frame_index += 1;

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

  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<commit_msg>Remove unused struct fields<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;

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

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<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.
  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<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.
  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 is_start    = true;
    let mut is_error    = false;
    let mut stream_info = StreamInfo::new();
    let mut metadata    = Vec::new();

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

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

          if is_last {
            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;
      let mut output  = Vec::with_capacity(output_size);

      unsafe { output.set_len(output_size) }

      Ok(Stream {
        info: stream_info,
        metadata: metadata,
        producer: producer,
        output: output,
      })
    } 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<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>;

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


<commit_before>// You should change this.
//
// Depending on your implementation, there are a variety of potential errors
// which might occur. They aren't checked by the test suite in order to
// allow the greatest freedom of implementation, but real libraries should
// provide useful, descriptive errors so that downstream code can react
// appropriately.
//
// One common idiom is to define an Error enum which wraps all potential
// errors. Another common idiom is to use a helper type such as failure::Error
// which does more or less the same thing but automatically.
pub type Error = ();

pub struct Scale;

impl Scale {
    pub fn new(tonic: &str, intervals: &str) -> Result<Scale, Error> {
        unimplemented!(
            "Construct a new scale with tonic {} and intervals {}",
            tonic,
            intervals
        )
    }

    pub fn chromatic(tonic: &str) -> Result<Scale, Error> {
        unimplemented!("Construct a new chromatic scale with tonic {}", tonic)
    }

    pub fn enumerate(&self) -> Vec<String> {
        unimplemented!()
    }
}
<commit_msg>fix new lints for scale-generator<commit_after>// You should change this.
//
// Depending on your implementation, there are a variety of potential errors
// which might occur. They aren't checked by the test suite in order to
// allow the greatest freedom of implementation, but real libraries should
// provide useful, descriptive errors so that downstream code can react
// appropriately.
//
// One common idiom is to define an Error enum which wraps all potential
// errors. Another common idiom is to use a helper type such as failure::Error
// which does more or less the same thing but automatically.
pub struct Error;

pub struct Scale;

impl Scale {
    pub fn new(tonic: &str, intervals: &str) -> Result<Scale, Error> {
        unimplemented!(
            "Construct a new scale with tonic {} and intervals {}",
            tonic,
            intervals
        )
    }

    pub fn chromatic(tonic: &str) -> Result<Scale, Error> {
        unimplemented!("Construct a new chromatic scale with tonic {}", tonic)
    }

    pub fn enumerate(&self) -> Vec<String> {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>use ndarray::*;
use ndarray_linalg::*;

#[test]
fn dgeev() {
    // https://software.intel.com/sites/products/documentation/doclib/mkl_sa/11/mkl_lapack_examples/dgeev_ex.f.htm
    let a: Array2<f64> = arr2(&[
        [-1.01, 0.86, -4.60, 3.31, -4.81],
        [3.98, 0.53, -7.04, 5.29, 3.55],
        [3.30, 8.26, -3.89, 8.20, -1.51],
        [4.43, 4.96, -7.66, -7.33, 6.18],
        [7.31, -6.43, -6.16, 2.47, 5.58],
    ]);
    let (e, vecs): (Array1<_>, Array2<_>) = (&a).eig().unwrap();
    assert_close_l2!(
        &e,
        &arr1(&[
            c64::new(2.86, 10.76),
            c64::new(2.86, -10.76),
            c64::new(-0.69, 4.70),
            c64::new(-0.69, -4.70),
            c64::new(-10.46, 0.00)
        ]),
        1.0e-3
    );

    /*
    let answer = &arr2(&[[c64::new(  0.11,  0.17), c64::new(  0.11, -0.17), c64::new(  0.73,  0.00), c64::new(  0.73,  0.00), c64::new(  0.46,  0.00)],
                         [c64::new(  0.41, -0.26), c64::new(  0.41,  0.26), c64::new( -0.03, -0.02), c64::new( -0.03,  0.02), c64::new(  0.34,  0.00)],
                         [c64::new(  0.10, -0.51), c64::new(  0.10,  0.51), c64::new(  0.19, -0.29), c64::new(  0.19,  0.29), c64::new(  0.31,  0.00)],
                         [c64::new(  0.40, -0.09), c64::new(  0.40,  0.09), c64::new( -0.08, -0.08), c64::new( -0.08,  0.08), c64::new( -0.74,  0.00)],
                         [c64::new(  0.54,  0.00), c64::new(  0.54,  0.00), c64::new( -0.29, -0.49), c64::new( -0.29,  0.49), c64::new(  0.16,  0.00)]]);
    */

    let a_c: Array2<c64> = a.map(|f| c64::new(*f, 0.0));
    for (i, v) in vecs.axis_iter(Axis(1)).enumerate() {
        let av = a_c.dot(&v);
        let ev = v.mapv(|f| e[i] * f);
        assert_close_l2!(&av, &ev, 1.0e-7);
    }
}

#[test]
fn fgeev() {
    // https://software.intel.com/sites/products/documentation/doclib/mkl_sa/11/mkl_lapack_examples/dgeev_ex.f.htm
    let a: Array2<f32> = arr2(&[
        [-1.01, 0.86, -4.60, 3.31, -4.81],
        [3.98, 0.53, -7.04, 5.29, 3.55],
        [3.30, 8.26, -3.89, 8.20, -1.51],
        [4.43, 4.96, -7.66, -7.33, 6.18],
        [7.31, -6.43, -6.16, 2.47, 5.58],
    ]);
    let (e, vecs): (Array1<_>, Array2<_>) = (&a).eig().unwrap();
    assert_close_l2!(
        &e,
        &arr1(&[
            c32::new(2.86, 10.76),
            c32::new(2.86, -10.76),
            c32::new(-0.69, 4.70),
            c32::new(-0.69, -4.70),
            c32::new(-10.46, 0.00)
        ]),
        1.0e-3
    );

    /*
    let answer = &arr2(&[[c32::new(  0.11,  0.17), c32::new(  0.11, -0.17), c32::new(  0.73,  0.00), c32::new(  0.73,  0.00), c32::new(  0.46,  0.00)],
                         [c32::new(  0.41, -0.26), c32::new(  0.41,  0.26), c32::new( -0.03, -0.02), c32::new( -0.03,  0.02), c32::new(  0.34,  0.00)],
                         [c32::new(  0.10, -0.51), c32::new(  0.10,  0.51), c32::new(  0.19, -0.29), c32::new(  0.19,  0.29), c32::new(  0.31,  0.00)],
                         [c32::new(  0.40, -0.09), c32::new(  0.40,  0.09), c32::new( -0.08, -0.08), c32::new( -0.08,  0.08), c32::new( -0.74,  0.00)],
                         [c32::new(  0.54,  0.00), c32::new(  0.54,  0.00), c32::new( -0.29, -0.49), c32::new( -0.29,  0.49), c32::new(  0.16,  0.00)]]);
    */

    let a_c: Array2<c32> = a.map(|f| c32::new(*f, 0.0));
    for (i, v) in vecs.axis_iter(Axis(1)).enumerate() {
        let av = a_c.dot(&v);
        let ev = v.mapv(|f| e[i] * f);
        assert_close_l2!(&av, &ev, 1.0e-5);
    }
}

#[test]
fn zgeev() {
    // https://software.intel.com/sites/products/documentation/doclib/mkl_sa/11/mkl_lapack_examples/zgeev_ex.f.htm
    let a: Array2<c64> = arr2(&[
        [
            c64::new(-3.84, 2.25),
            c64::new(-8.94, -4.75),
            c64::new(8.95, -6.53),
            c64::new(-9.87, 4.82),
        ],
        [
            c64::new(-0.66, 0.83),
            c64::new(-4.40, -3.82),
            c64::new(-3.50, -4.26),
            c64::new(-3.15, 7.36),
        ],
        [
            c64::new(-3.99, -4.73),
            c64::new(-5.88, -6.60),
            c64::new(-3.36, -0.40),
            c64::new(-0.75, 5.23),
        ],
        [
            c64::new(7.74, 4.18),
            c64::new(3.66, -7.53),
            c64::new(2.58, 3.60),
            c64::new(4.59, 5.41),
        ],
    ]);
    let (e, vecs): (Array1<_>, Array2<_>) = (&a).eig().unwrap();
    assert_close_l2!(
        &e,
        &arr1(&[
            c64::new(-9.43, -12.98),
            c64::new(-3.44, 12.69),
            c64::new(0.11, -3.40),
            c64::new(5.76, 7.13)
        ]),
        1.0e-3
    );

    /*
    let answer = &arr2(&[[c64::new(  0.43,  0.33), c64::new(  0.83,  0.00), c64::new(  0.60,  0.00), c64::new( -0.31,  0.03)],
                         [c64::new(  0.51, -0.03), c64::new(  0.08, -0.25), c64::new( -0.40, -0.20), c64::new(  0.04,  0.34)],
                         [c64::new(  0.62,  0.00), c64::new( -0.25,  0.28), c64::new( -0.09, -0.48), c64::new(  0.36,  0.06)],
                         [c64::new( -0.23,  0.11), c64::new( -0.10, -0.32), c64::new( -0.43,  0.13), c64::new(  0.81,  0.00)]]);
    */

    for (i, v) in vecs.axis_iter(Axis(1)).enumerate() {
        let av = a.dot(&v);
        let ev = v.mapv(|f| e[i] * f);
        assert_close_l2!(&av, &ev, 1.0e-7);
    }
}

#[test]
fn cgeev() {
    // https://software.intel.com/sites/products/documentation/doclib/mkl_sa/11/mkl_lapack_examples/zgeev_ex.f.htm
    let a: Array2<c32> = arr2(&[
        [
            c32::new(-3.84, 2.25),
            c32::new(-8.94, -4.75),
            c32::new(8.95, -6.53),
            c32::new(-9.87, 4.82),
        ],
        [
            c32::new(-0.66, 0.83),
            c32::new(-4.40, -3.82),
            c32::new(-3.50, -4.26),
            c32::new(-3.15, 7.36),
        ],
        [
            c32::new(-3.99, -4.73),
            c32::new(-5.88, -6.60),
            c32::new(-3.36, -0.40),
            c32::new(-0.75, 5.23),
        ],
        [
            c32::new(7.74, 4.18),
            c32::new(3.66, -7.53),
            c32::new(2.58, 3.60),
            c32::new(4.59, 5.41),
        ],
    ]);
    let (e, vecs): (Array1<_>, Array2<_>) = (&a).eig().unwrap();
    assert_close_l2!(
        &e,
        &arr1(&[
            c32::new(-9.43, -12.98),
            c32::new(-3.44, 12.69),
            c32::new(0.11, -3.40),
            c32::new(5.76, 7.13)
        ]),
        1.0e-3
    );

    /*
    let answer = &arr2(&[[c32::new(  0.43,  0.33), c32::new(  0.83,  0.00), c32::new(  0.60,  0.00), c32::new( -0.31,  0.03)],
                         [c32::new(  0.51, -0.03), c32::new(  0.08, -0.25), c32::new( -0.40, -0.20), c32::new(  0.04,  0.34)],
                         [c32::new(  0.62,  0.00), c32::new( -0.25,  0.28), c32::new( -0.09, -0.48), c32::new(  0.36,  0.06)],
                         [c32::new( -0.23,  0.11), c32::new( -0.10, -0.32), c32::new( -0.43,  0.13), c32::new(  0.81,  0.00)]]);
    */

    for (i, v) in vecs.axis_iter(Axis(1)).enumerate() {
        let av = a.dot(&v);
        let ev = v.mapv(|f| e[i] * f);
        assert_close_l2!(&av, &ev, 1.0e-5);
    }
}
<commit_msg>Split eigenvalue and eigenvector tests<commit_after>use ndarray::*;
use ndarray_linalg::*;

// Test Av_i = e_i v_i for i = 0..n
fn test_eig<T: Scalar>(a: Array2<T>, eigs: Array1<T::Complex>, vecs: Array2<T::Complex>)
where
    T::Complex: Lapack,
{
    println!("a\n{:+.4}", &a);
    println!("eigs\n{:+.4}", &eigs);
    println!("vec\n{:+.4}", &vecs);
    let a: Array2<T::Complex> = a.map(|v| v.as_c());
    for (&e, v) in eigs.iter().zip(vecs.axis_iter(Axis(1))) {
        let av = a.dot(&v);
        let ev = v.mapv(|val| val * e);
        println!("av = {:+.4}", &av);
        println!("ev = {:+.4}", &ev);
        assert_close_l2!(&av, &ev, T::real(1e-3));
    }
}

// Test case for real Eigenvalue problem
//
//  -1.01   0.86  -4.60   3.31  -4.81
//   3.98   0.53  -7.04   5.29   3.55
//   3.30   8.26  -3.89   8.20  -1.51
//   4.43   4.96  -7.66  -7.33   6.18
//   7.31  -6.43  -6.16   2.47   5.58
//
// Eigenvalues
// (  2.86, 10.76) (  2.86,-10.76) ( -0.69,  4.70) ( -0.69, -4.70) -10.46
//
// Left eigenvectors
// (  0.04,  0.29) (  0.04, -0.29) ( -0.13, -0.33) ( -0.13,  0.33)   0.04
// (  0.62,  0.00) (  0.62,  0.00) (  0.69,  0.00) (  0.69,  0.00)   0.56
// ( -0.04, -0.58) ( -0.04,  0.58) ( -0.39, -0.07) ( -0.39,  0.07)  -0.13
// (  0.28,  0.01) (  0.28, -0.01) ( -0.02, -0.19) ( -0.02,  0.19)  -0.80
// ( -0.04,  0.34) ( -0.04, -0.34) ( -0.40,  0.22) ( -0.40, -0.22)   0.18
//
// Right eigenvectors
// (  0.11,  0.17) (  0.11, -0.17) (  0.73,  0.00) (  0.73,  0.00)   0.46
// (  0.41, -0.26) (  0.41,  0.26) ( -0.03, -0.02) ( -0.03,  0.02)   0.34
// (  0.10, -0.51) (  0.10,  0.51) (  0.19, -0.29) (  0.19,  0.29)   0.31
// (  0.40, -0.09) (  0.40,  0.09) ( -0.08, -0.08) ( -0.08,  0.08)  -0.74
// (  0.54,  0.00) (  0.54,  0.00) ( -0.29, -0.49) ( -0.29,  0.49)   0.16
//
// - https://software.intel.com/sites/products/documentation/doclib/mkl_sa/11/mkl_lapack_examples/dgeev_ex.f.htm
//
fn test_matrix_real<T: Scalar>() -> Array2<T::Real> {
    array![
        [
            T::real(-1.01),
            T::real(0.86),
            T::real(-4.60),
            T::real(3.31),
            T::real(-4.81)
        ],
        [
            T::real(3.98),
            T::real(0.53),
            T::real(-7.04),
            T::real(5.29),
            T::real(3.55)
        ],
        [
            T::real(3.30),
            T::real(8.26),
            T::real(-3.89),
            T::real(8.20),
            T::real(-1.51)
        ],
        [
            T::real(4.43),
            T::real(4.96),
            T::real(-7.66),
            T::real(-7.33),
            T::real(6.18)
        ],
        [
            T::real(7.31),
            T::real(-6.43),
            T::real(-6.16),
            T::real(2.47),
            T::real(5.58)
        ],
    ]
}

fn test_matrix_real_t<T: Scalar>() -> Array2<T::Real> {
    test_matrix_real::<T>().t().permuted_axes([1, 0]).to_owned()
}

fn answer_eig_real<T: Scalar>() -> Array1<T::Complex> {
    array![
        T::complex(-10.46, 0.00),
        T::complex(-0.69, 4.70),
        T::complex(-0.69, -4.70),
        T::complex(2.86, 10.76),
        T::complex(2.86, -10.76),
    ]
}

// Test case for {c,z}geev
//
// ( -3.84,  2.25) ( -8.94, -4.75) (  8.95, -6.53) ( -9.87,  4.82)
// ( -0.66,  0.83) ( -4.40, -3.82) ( -3.50, -4.26) ( -3.15,  7.36)
// ( -3.99, -4.73) ( -5.88, -6.60) ( -3.36, -0.40) ( -0.75,  5.23)
// (  7.74,  4.18) (  3.66, -7.53) (  2.58,  3.60) (  4.59,  5.41)
//
// Eigenvalues
// ( -9.43,-12.98) ( -3.44, 12.69) (  0.11, -3.40) (  5.76,  7.13)
//
// Left eigenvectors
// (  0.24, -0.18) (  0.61,  0.00) ( -0.18, -0.33) (  0.28,  0.09)
// (  0.79,  0.00) ( -0.05, -0.27) (  0.82,  0.00) ( -0.55,  0.16)
// (  0.22, -0.27) ( -0.21,  0.53) ( -0.37,  0.15) (  0.45,  0.09)
// ( -0.02,  0.41) (  0.40, -0.24) (  0.06,  0.12) (  0.62,  0.00)
//
// Right eigenvectors
// (  0.43,  0.33) (  0.83,  0.00) (  0.60,  0.00) ( -0.31,  0.03)
// (  0.51, -0.03) (  0.08, -0.25) ( -0.40, -0.20) (  0.04,  0.34)
// (  0.62,  0.00) ( -0.25,  0.28) ( -0.09, -0.48) (  0.36,  0.06)
// ( -0.23,  0.11) ( -0.10, -0.32) ( -0.43,  0.13) (  0.81,  0.00)
//
// - https://software.intel.com/sites/products/documentation/doclib/mkl_sa/11/mkl_lapack_examples/zgeev_ex.f.htm
//
fn test_matrix_complex<T: Scalar>() -> Array2<T::Complex> {
    array![
        [
            T::complex(-3.84, 2.25),
            T::complex(-8.94, -4.75),
            T::complex(8.95, -6.53),
            T::complex(-9.87, 4.82)
        ],
        [
            T::complex(-0.66, 0.83),
            T::complex(-4.40, -3.82),
            T::complex(-3.50, -4.26),
            T::complex(-3.15, 7.36)
        ],
        [
            T::complex(-3.99, -4.73),
            T::complex(-5.88, -6.60),
            T::complex(-3.36, -0.40),
            T::complex(-0.75, 5.23)
        ],
        [
            T::complex(7.74, 4.18),
            T::complex(3.66, -7.53),
            T::complex(2.58, 3.60),
            T::complex(4.59, 5.41)
        ]
    ]
}

fn test_matrix_complex_t<T: Scalar>() -> Array2<T::Complex> {
    test_matrix_complex::<T>()
        .t()
        .permuted_axes([1, 0])
        .to_owned()
}

fn answer_eig_complex<T: Scalar>() -> Array1<T::Complex> {
    array![
        T::complex(-9.43, -12.98),
        T::complex(-3.44, 12.69),
        T::complex(0.11, -3.40),
        T::complex(5.76, 7.13)
    ]
}

// re-evaluated eigenvalues in f64 accuracy
fn answer_eigvectors_complex<T: Scalar>() -> Array2<T::Complex> {
    array![
        [
            T::complex(0.4308565200776108, 0.32681273781262143),
            T::complex(0.8256820507672813, 0.),
            T::complex(0.5983959785539453, 0.),
            T::complex(-0.30543190348437826, 0.03333164861799901)
        ],
        [
            T::complex(0.5087414602970965, -0.02883342170692809),
            T::complex(0.07502916788141115, -0.2487285045091665),
            T::complex(-0.40047616275207687, -0.2014492227625603),
            T::complex(0.03978282815783273, 0.34450765221546126)
        ],
        [
            T::complex(0.6198496527657755, 0.),
            T::complex(-0.24575578997801528, 0.27887240221169646),
            T::complex(-0.09008001907594984, -0.4752646215391732),
            T::complex(0.3583254365159844, 0.06064506988524665)
        ],
        [
            T::complex(-0.22692824331926856, 0.11043927846403584),
            T::complex(-0.10343406372814358, -0.3192014653632327),
            T::complex(-0.43484029549540404, 0.13372491785816037),
            T::complex(0.8082432893178352, 0.)
        ]
    ]
}

macro_rules! impl_test_real {
    ($real:ty) => {
        paste::item! {
            #[test]
            fn [<$real _eigvals >]() {
                let a = test_matrix_real::<$real>();
                let (e, _vecs) = a.eig().unwrap();
                assert_close_l2!(&e, &answer_eig_real::<$real>(), 1.0e-3);
            }

            #[test]
            fn [<$real _eigvals_t>]() {
                let a = test_matrix_real_t::<$real>();
                let (e, _vecs) = a.eig().unwrap();
                assert_close_l2!(&e, &answer_eig_real::<$real>(), 1.0e-3);
            }

            #[test]
            fn [<$real _eig>]() {
                let a = test_matrix_real::<$real>();
                let (e, vecs) = a.eig().unwrap();
                test_eig(a, e, vecs);
            }

            #[test]
            fn [<$real _eig_t>]() {
                let a = test_matrix_real_t::<$real>();
                let (e, vecs) = a.eig().unwrap();
                test_eig(a, e, vecs);
            }

        } // paste::item!
    };
}

impl_test_real!(f32);
impl_test_real!(f64);

macro_rules! impl_test_complex {
    ($complex:ty) => {
        paste::item! {
            #[test]
            fn [<$complex _eigvals >]() {
                let a = test_matrix_complex::<$complex>();
                let (e, _vecs) = a.eig().unwrap();
                assert_close_l2!(&e, &answer_eig_complex::<$complex>(), 1.0e-3);
            }

            #[test]
            fn [<$complex _eigvals_t>]() {
                let a = test_matrix_complex_t::<$complex>();
                let (e, _vecs) = a.eig().unwrap();
                assert_close_l2!(&e, &answer_eig_complex::<$complex>(), 1.0e-3);
            }

            #[test]
            fn [<$complex _eigvector>]() {
                let a = test_matrix_complex::<$complex>();
                let (_e, vecs) = a.eig().unwrap();
                assert_close_l2!(&vecs, &answer_eigvectors_complex::<$complex>(), 1.0e-3);
            }

            #[test]
            fn [<$complex _eigvector_t>]() {
                let a = test_matrix_complex_t::<$complex>();
                let (_e, vecs) = a.eig().unwrap();
                assert_close_l2!(&vecs, &answer_eigvectors_complex::<$complex>(), 1.0e-3);
            }

            #[test]
            fn [<$complex _eig>]() {
                let a = test_matrix_complex::<$complex>();
                let (e, vecs) = a.eig().unwrap();
                test_eig(a, e, vecs);
            }

            #[test]
            fn [<$complex _eig_t>]() {
                let a = test_matrix_complex_t::<$complex>();
                let (e, vecs) = a.eig().unwrap();
                test_eig(a, e, vecs);
            }
        } // paste::item!
    };
}

impl_test_complex!(c32);
impl_test_complex!(c64);
<|endoftext|>


<commit_before>use futures_core::future::Future;
use futures_core::task::{Context, Poll};
use pin_utils::{unsafe_pinned, unsafe_unpinned};
use std::marker::PhantomPinned;
use std::pin::Pin;
use std::ptr;
use std::thread::panicking;

/// Combinator for the
/// [`FutureTestExt::assert_unmoved`](super::FutureTestExt::assert_unmoved)
/// method.
#[derive(Debug, Clone)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct AssertUnmoved<Fut> {
    future: Fut,
    this_ptr: *const AssertUnmoved<Fut>,
    _pinned: PhantomPinned,
}

impl<Fut> AssertUnmoved<Fut> {
    unsafe_pinned!(future: Fut);
    unsafe_unpinned!(this_ptr: *const Self);

    pub(super) fn new(future: Fut) -> Self {
        Self {
            future,
            this_ptr: ptr::null(),
            _pinned: PhantomPinned,
        }
    }
}

impl<Fut: Future> Future for AssertUnmoved<Fut> {
    type Output = Fut::Output;

    fn poll(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Self::Output> {
        let cur_this = &*self as *const Self;
        if self.this_ptr.is_null() {
            // First time being polled
            *self.as_mut().this_ptr() = cur_this;
        } else {
            assert_eq!(self.this_ptr, cur_this, "Future moved between poll calls");
        }
        self.as_mut().future().poll(cx)
    }
}

impl<Fut> Drop for AssertUnmoved<Fut> {
    fn drop(&mut self) {
        // If the thread is panicking then we can't panic again as that will
        // cause the process to be aborted.
        if !panicking() && !self.this_ptr.is_null() {
            let cur_this = &*self as *const Self;
            assert_eq!(self.this_ptr, cur_this, "Future moved before drop");
        }
    }
}

#[cfg(test)]
mod tests {
    use futures_core::future::Future;
    use futures_core::task::{Context, Poll};
    use futures_util::future::pending;
    use futures_util::task::noop_waker;
    use std::pin::Pin;

    use super::AssertUnmoved;

    #[test]
    fn dont_panic_when_not_polled() {
        // This shouldn't panic.
        let future = AssertUnmoved::new(pending::<()>());
        drop(future);
    }

    #[test]
    #[should_panic(expected = "Future moved between poll calls")]
    fn dont_double_panic() {
        // This test should only panic, not abort the process.
        let waker = noop_waker();
        let mut cx = Context::from_waker(&waker);

        // First we allocate the future on the stack and poll it.
        let mut future = AssertUnmoved::new(pending::<()>());
        let pinned_future = unsafe { Pin::new_unchecked(&mut future) };
        assert_eq!(pinned_future.poll(&mut cx), Poll::Pending);

        // Next we move it back to the heap and poll it again. This second call
        // should panic (as the future is moved), but we shouldn't panic again
        // whilst dropping `AssertUnmoved`.
        let mut future = Box::new(future);
        let pinned_boxed_future = unsafe { Pin::new_unchecked(&mut *future) };
        assert_eq!(pinned_boxed_future.poll(&mut cx), Poll::Pending);
    }
}
<commit_msg>Implement Send + Sync for AssertUnmoved<commit_after>use futures_core::future::Future;
use futures_core::task::{Context, Poll};
use pin_utils::{unsafe_pinned, unsafe_unpinned};
use std::marker::PhantomPinned;
use std::pin::Pin;
use std::ptr;
use std::thread::panicking;

/// Combinator for the
/// [`FutureTestExt::assert_unmoved`](super::FutureTestExt::assert_unmoved)
/// method.
#[derive(Debug, Clone)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct AssertUnmoved<Fut> {
    future: Fut,
    this_ptr: *const AssertUnmoved<Fut>,
    _pinned: PhantomPinned,
}

// Safety: having a raw pointer in a struct makes it `!Send`, however the
// pointer is never dereferenced so this is safe.
unsafe impl<Fut: Sync + Send> Send for AssertUnmoved<Fut> {}
unsafe impl<Fut: Sync + Send> Sync for AssertUnmoved<Fut> {}

impl<Fut> AssertUnmoved<Fut> {
    unsafe_pinned!(future: Fut);
    unsafe_unpinned!(this_ptr: *const Self);

    pub(super) fn new(future: Fut) -> Self {
        Self {
            future,
            this_ptr: ptr::null(),
            _pinned: PhantomPinned,
        }
    }
}

impl<Fut: Future> Future for AssertUnmoved<Fut> {
    type Output = Fut::Output;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let cur_this = &*self as *const Self;
        if self.this_ptr.is_null() {
            // First time being polled
            *self.as_mut().this_ptr() = cur_this;
        } else {
            assert_eq!(self.this_ptr, cur_this, "Future moved between poll calls");
        }
        self.as_mut().future().poll(cx)
    }
}

impl<Fut> Drop for AssertUnmoved<Fut> {
    fn drop(&mut self) {
        // If the thread is panicking then we can't panic again as that will
        // cause the process to be aborted.
        if !panicking() && !self.this_ptr.is_null() {
            let cur_this = &*self as *const Self;
            assert_eq!(self.this_ptr, cur_this, "Future moved before drop");
        }
    }
}

#[cfg(test)]
mod tests {
    use futures_core::future::Future;
    use futures_core::task::{Context, Poll};
    use futures_util::future::pending;
    use futures_util::task::noop_waker;
    use std::pin::Pin;

    use super::AssertUnmoved;

    #[test]
    fn assert_send_sync() {
        fn assert<T: Send + Sync>() {}
        assert::<AssertUnmoved<()>>();
    }

    #[test]
    fn dont_panic_when_not_polled() {
        // This shouldn't panic.
        let future = AssertUnmoved::new(pending::<()>());
        drop(future);
    }

    #[test]
    #[should_panic(expected = "Future moved between poll calls")]
    fn dont_double_panic() {
        // This test should only panic, not abort the process.
        let waker = noop_waker();
        let mut cx = Context::from_waker(&waker);

        // First we allocate the future on the stack and poll it.
        let mut future = AssertUnmoved::new(pending::<()>());
        let pinned_future = unsafe { Pin::new_unchecked(&mut future) };
        assert_eq!(pinned_future.poll(&mut cx), Poll::Pending);

        // Next we move it back to the heap and poll it again. This second call
        // should panic (as the future is moved), but we shouldn't panic again
        // whilst dropping `AssertUnmoved`.
        let mut future = Box::new(future);
        let pinned_boxed_future = unsafe { Pin::new_unchecked(&mut *future) };
        assert_eq!(pinned_boxed_future.poll(&mut cx), Poll::Pending);
    }
}
<|endoftext|>


<commit_before>use token::Token;
use logger::Logger;
use error::{Error, Result, Source};

use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::borrow::Cow;
use std::fs;
use std::io::Read;

use walkdir::WalkDir;
use rustc_serialize::base64::{self, ToBase64};
use mime_guess;

/// Resource Handler.
///
/// Its task is to make sure that some resource (image, link) is available
/// for the book and to list images used in Markdown files so they can be used for the book
#[derive(Debug)]
pub struct ResourceHandler<'r> {
    /// Maps an original url (e.g.) "foo/Readme.md" to a valid link
    /// (e.g.) chapter3.html
    links: HashMap<String, String>,
    map_images: bool,
    logger: &'r Logger,
    base64: bool,

    /// Maps an original (local) file name to a new file name. Allows to
    /// make sure all image files will be included in e.g. the Epub document.
    #[doc(hidden)]
    pub images: HashMap<String, String>,
}

impl<'r> ResourceHandler<'r> {
    /// Creates a new, empty Resource Handler
    pub fn new(logger: &'r Logger) -> ResourceHandler {
        ResourceHandler {
            links: HashMap::new(),
            images: HashMap::new(),
            map_images: false,
            base64: false,
            logger: logger,
        }
    }

    /// Turns on mapping for image files
    ///
    /// # Argument: an offset (should be book.root)
    pub fn set_images_mapping(&mut self, b: bool) -> &mut Self {
        self.map_images = b;
        self
    }

    /// Sets base64 mode for image mapping
    ///
    /// If set to true, instead of returning a destination file path,
    /// `map_image` will include the image as base64
    pub fn set_base64(&mut self, b: bool) {
        self.base64 = b;
    }

    /// Add a local image file and get the resulting transformed
    /// file name
    pub fn map_image<'a, S: Into<Cow<'a, str>>>(&'a mut self,
                                                source: &Source,
                                                file: S)
                                                -> Result<Cow<'a, str>> {
        // If image is not local, do nothing much
        let file = file.into();
        if !Self::is_local(file.as_ref()) {
            self.logger
                .warning(lformat!("Resources: book includes non-local image {file}, which might \
                                   cause problem for proper inclusion.",
                                  file = file));
            return Ok(file);
        }

        // Check exisence of the file
        if fs::metadata(file.as_ref()).is_err() {
            return Err(Error::file_not_found(source, lformat!("image"), format!("{}", file)));
        }

        // if image mapping is not activated do nothing else
        if !self.map_images {
            return Ok(file);
        }

        // If this image has already been registered, returns it
        if self.images.contains_key(file.as_ref()) {
            return Ok(Cow::Borrowed(&self.images[file.as_ref()]));
        }

        // Else, create a new file name that has same extension
        // (or a base64 version of the file)
        let dest_file = if !(self.base64) {
            if let Some(extension) = Path::new(file.as_ref()).extension() {
                format!("images/image_{}.{}",
                        self.images.len(),
                        extension.to_string_lossy())
            } else {
                self.logger
                    .warning(lformat!("Resources: book includes image {file} which doesn't have \
                                       an extension",
                                      file = file));
                format!("images/image_{}", self.images.len())
            }
        } else {
            let mut f = match fs::File::open(file.as_ref()) {
                Ok(f) => f,
                Err(_) => {
                    return Err(Error::file_not_found(source,
                                                     lformat!("image"),
                                                     format!("{}", file)));
                }
            };
            let mut content: Vec<u8> = vec![];
            if f.read_to_end(&mut content).is_err() {
                self.logger.error(lformat!("Resources: could not read file {file}", file = file));
                return Ok(file);
            }
            let base64 = content.to_base64(base64::STANDARD);
            match mime_guess::guess_mime_type_opt(file.as_ref()) {
                None => {
                    self.logger
                        .error(lformat!("Resources: could not guess mime type of file {file}",
                                        file = file));
                    return Ok(file);
                }
                Some(s) => format!("data:{};base64,{}", s.to_string(), base64),
            }
        };

        self.images.insert(file.into_owned(), dest_file.clone());
        Ok(Cow::Owned(dest_file))
    }

    /// Returns an iterator the the images files mapping
    #[doc(hidden)]
    pub fn images_mapping(&self) -> &HashMap<String, String> {
        &self.images
    }

    /// Add a match between an original file and a dest file
    pub fn add_link<S1: Into<String>, S2:Into<String>>(&mut self, from: S1, to: S2) {
        self.links.insert(from.into(), to.into());
    }

    /// Get a destination link from an original link
    pub fn get_link<'a>(&'a self, from: &'a str) -> &'a str {
        if let Some(link) = self.links.get(from) {
            link
        } else {
            self.logger.error(lformat!("Resources: could not find a in-book match for link \
                                        {file}",
                                       file = from));
            from
        }
    }

    /// Tell whether a file name is a local resource or net
    pub fn is_local(path: &str) -> bool {
        !path.contains("://") // todo: use better algorithm
    }

    /// Add a path offset to all linked urls and images src
    pub fn add_offset(link_offset: &Path, image_offset: &Path, ast: &mut [Token]) {
        if link_offset == Path::new("") && image_offset == Path::new("") {
            // nothing do to
            return;
        }
        for mut token in ast {
            match *token {
                Token::Link(ref mut url, _, ref mut v) => {
                    if ResourceHandler::is_local(url) {
                        let new_url = format!("{}", link_offset.join(&url).display());
                        *url = new_url;
                    }
                    Self::add_offset(link_offset, image_offset, v);
                }
                Token::Image(ref mut url, _, ref mut v) |
                Token::StandaloneImage(ref mut url, _, ref mut v) => {
                    if ResourceHandler::is_local(url) {
                        let new_url = format!("{}", image_offset.join(&url).display());
                        *url = new_url;
                    }
                    Self::add_offset(link_offset, image_offset, v);
                }
                _ => {
                    if let Some(ref mut inner) = token.inner_mut() {
                        Self::add_offset(link_offset, image_offset, inner);
                    }
                }
            }
        }
    }
}

/// Get the list of all files, walking recursively in directories
///
/// # Arguments
/// - list: a list of files
/// - base: the path where to get them
///
/// # Returns
/// A list of files (relative to `base`), or an error.
pub fn get_files(list: Vec<String>, base: &str) -> Result<Vec<String>> {
    let mut out: Vec<String> = vec![];
    let base = Path::new(base);
    for path in list {
        let abs_path = base.join(&path);
        let res = fs::metadata(&abs_path);
        match res {
            Err(err) => {
                return Err(Error::render(Source::empty(),
                                         lformat!("error reading file {file}: {error}",
                                                  file = abs_path.display(),
                                                  error = err)))
            }
            Ok(metadata) => {
                if metadata.is_file() {
                    out.push(path);
                } else if metadata.is_dir() {
                    let files = WalkDir::new(&abs_path)
                        .follow_links(true)
                        .into_iter()
                        .filter_map(|e| e.ok())
                        .filter(|e| e.file_type().is_file())
                        .map(|e| {
                            PathBuf::from(e.path()
                                .strip_prefix(base)
                                .unwrap())
                        });
                    for file in files {
                        out.push(file.to_string_lossy().into_owned());
                    }
                } else {
                    return Err(Error::render(Source::empty(),
                                             lformat!("error in epub rendering: {path} is \
                                                       neither a file nor a directory",
                                                      path = &path)));
                }
            }
        }
    }
    Ok(out)
}
<commit_msg>Fix typo in error message for link not found and move it to warning<commit_after>use token::Token;
use logger::Logger;
use error::{Error, Result, Source};

use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::borrow::Cow;
use std::fs;
use std::io::Read;

use walkdir::WalkDir;
use rustc_serialize::base64::{self, ToBase64};
use mime_guess;

/// Resource Handler.
///
/// Its task is to make sure that some resource (image, link) is available
/// for the book and to list images used in Markdown files so they can be used for the book
#[derive(Debug)]
pub struct ResourceHandler<'r> {
    /// Maps an original url (e.g.) "foo/Readme.md" to a valid link
    /// (e.g.) chapter3.html
    links: HashMap<String, String>,
    map_images: bool,
    logger: &'r Logger,
    base64: bool,

    /// Maps an original (local) file name to a new file name. Allows to
    /// make sure all image files will be included in e.g. the Epub document.
    #[doc(hidden)]
    pub images: HashMap<String, String>,
}

impl<'r> ResourceHandler<'r> {
    /// Creates a new, empty Resource Handler
    pub fn new(logger: &'r Logger) -> ResourceHandler {
        ResourceHandler {
            links: HashMap::new(),
            images: HashMap::new(),
            map_images: false,
            base64: false,
            logger: logger,
        }
    }

    /// Turns on mapping for image files
    ///
    /// # Argument: an offset (should be book.root)
    pub fn set_images_mapping(&mut self, b: bool) -> &mut Self {
        self.map_images = b;
        self
    }

    /// Sets base64 mode for image mapping
    ///
    /// If set to true, instead of returning a destination file path,
    /// `map_image` will include the image as base64
    pub fn set_base64(&mut self, b: bool) {
        self.base64 = b;
    }

    /// Add a local image file and get the resulting transformed
    /// file name
    pub fn map_image<'a, S: Into<Cow<'a, str>>>(&'a mut self,
                                                source: &Source,
                                                file: S)
                                                -> Result<Cow<'a, str>> {
        // If image is not local, do nothing much
        let file = file.into();
        if !Self::is_local(file.as_ref()) {
            self.logger
                .warning(lformat!("Resources: book includes non-local image {file}, which might \
                                   cause problem for proper inclusion.",
                                  file = file));
            return Ok(file);
        }

        // Check exisence of the file
        if fs::metadata(file.as_ref()).is_err() {
            return Err(Error::file_not_found(source, lformat!("image"), format!("{}", file)));
        }

        // if image mapping is not activated do nothing else
        if !self.map_images {
            return Ok(file);
        }

        // If this image has already been registered, returns it
        if self.images.contains_key(file.as_ref()) {
            return Ok(Cow::Borrowed(&self.images[file.as_ref()]));
        }

        // Else, create a new file name that has same extension
        // (or a base64 version of the file)
        let dest_file = if !(self.base64) {
            if let Some(extension) = Path::new(file.as_ref()).extension() {
                format!("images/image_{}.{}",
                        self.images.len(),
                        extension.to_string_lossy())
            } else {
                self.logger
                    .warning(lformat!("Resources: book includes image {file} which doesn't have \
                                       an extension",
                                      file = file));
                format!("images/image_{}", self.images.len())
            }
        } else {
            let mut f = match fs::File::open(file.as_ref()) {
                Ok(f) => f,
                Err(_) => {
                    return Err(Error::file_not_found(source,
                                                     lformat!("image"),
                                                     format!("{}", file)));
                }
            };
            let mut content: Vec<u8> = vec![];
            if f.read_to_end(&mut content).is_err() {
                self.logger.error(lformat!("Resources: could not read file {file}", file = file));
                return Ok(file);
            }
            let base64 = content.to_base64(base64::STANDARD);
            match mime_guess::guess_mime_type_opt(file.as_ref()) {
                None => {
                    self.logger
                        .error(lformat!("Resources: could not guess mime type of file {file}",
                                        file = file));
                    return Ok(file);
                }
                Some(s) => format!("data:{};base64,{}", s.to_string(), base64),
            }
        };

        self.images.insert(file.into_owned(), dest_file.clone());
        Ok(Cow::Owned(dest_file))
    }

    /// Returns an iterator the the images files mapping
    #[doc(hidden)]
    pub fn images_mapping(&self) -> &HashMap<String, String> {
        &self.images
    }

    /// Add a match between an original file and a dest file
    pub fn add_link<S1: Into<String>, S2:Into<String>>(&mut self, from: S1, to: S2) {
        self.links.insert(from.into(), to.into());
    }

    /// Get a destination link from an original link
    pub fn get_link<'a>(&'a self, from: &'a str) -> &'a str {
        if let Some(link) = self.links.get(from) {
            link
        } else {
            self.logger.warning(lformat!("Resources: could not find an in-book match for link \
                                        {file}",
                                       file = from));
            from
        }
    }

    /// Tell whether a file name is a local resource or net
    pub fn is_local(path: &str) -> bool {
        !path.contains("://") // todo: use better algorithm
    }

    /// Add a path offset to all linked urls and images src
    pub fn add_offset(link_offset: &Path, image_offset: &Path, ast: &mut [Token]) {
        if link_offset == Path::new("") && image_offset == Path::new("") {
            // nothing do to
            return;
        }
        for mut token in ast {
            match *token {
                Token::Link(ref mut url, _, ref mut v) => {
                    if ResourceHandler::is_local(url) {
                        let new_url = format!("{}", link_offset.join(&url).display());
                        *url = new_url;
                    }
                    Self::add_offset(link_offset, image_offset, v);
                }
                Token::Image(ref mut url, _, ref mut v) |
                Token::StandaloneImage(ref mut url, _, ref mut v) => {
                    if ResourceHandler::is_local(url) {
                        let new_url = format!("{}", image_offset.join(&url).display());
                        *url = new_url;
                    }
                    Self::add_offset(link_offset, image_offset, v);
                }
                _ => {
                    if let Some(ref mut inner) = token.inner_mut() {
                        Self::add_offset(link_offset, image_offset, inner);
                    }
                }
            }
        }
    }
}

/// Get the list of all files, walking recursively in directories
///
/// # Arguments
/// - list: a list of files
/// - base: the path where to get them
///
/// # Returns
/// A list of files (relative to `base`), or an error.
pub fn get_files(list: Vec<String>, base: &str) -> Result<Vec<String>> {
    let mut out: Vec<String> = vec![];
    let base = Path::new(base);
    for path in list {
        let abs_path = base.join(&path);
        let res = fs::metadata(&abs_path);
        match res {
            Err(err) => {
                return Err(Error::render(Source::empty(),
                                         lformat!("error reading file {file}: {error}",
                                                  file = abs_path.display(),
                                                  error = err)))
            }
            Ok(metadata) => {
                if metadata.is_file() {
                    out.push(path);
                } else if metadata.is_dir() {
                    let files = WalkDir::new(&abs_path)
                        .follow_links(true)
                        .into_iter()
                        .filter_map(|e| e.ok())
                        .filter(|e| e.file_type().is_file())
                        .map(|e| {
                            PathBuf::from(e.path()
                                .strip_prefix(base)
                                .unwrap())
                        });
                    for file in files {
                        out.push(file.to_string_lossy().into_owned());
                    }
                } else {
                    return Err(Error::render(Source::empty(),
                                             lformat!("error in epub rendering: {path} is \
                                                       neither a file nor a directory",
                                                      path = &path)));
                }
            }
        }
    }
    Ok(out)
}
<|endoftext|>


<commit_before>//!
//! Values manipulated by endpoints
//!

use std::time::Duration;
use std::cmp::{PartialOrd, Ordering};

extern crate chrono;
use self::chrono::{DateTime, Local};

extern crate serde_json;

///
/// The type of values manipulated by endpoints.
///
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub enum Type {
    ///
    /// # Trivial values
    ///

    /// An empty value. Used for instance to inform that a countdown
    /// has reached 0 or that a device is ready.
    Unit,

    /// A boolean. Used for instance for on-off switches, presence
    /// detectors, etc.
    Bool,

    ///
    /// # Time
    ///

    /// A duration. Used for instance in countdowns.
    Duration,

    /// A precise timestamp. Used for instance to determine when an
    /// event has taken place.
    TimeStamp,

    Temperature,

    ///
    /// ...
    ///
    Color,
    Json,
    Binary,
}

/// A temperature. Internal representation may be either Fahrenheit or
/// Celcius. The FoxBox adapters are expected to perform conversions
/// to the format requested by their devices.
#[derive(Debug, Clone, PartialEq)]
pub enum Temperature {
    /// Fahrenheit
    F(f64),
    /// Celcius
    C(f64),
}

impl Temperature {
    /// Get a temperature in Fahrenheit.
    pub fn as_f(&self) -> f64 {
        unimplemented!();
    }

    /// Get a temperature in Celcius.
    pub fn as_c(&self) -> f64 {
        unimplemented!();
    }
}

impl PartialOrd for Temperature {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.as_c().partial_cmp(&other.as_c())
    }
}

/// A color. Internal representation may vary. The FoxBox adapters are
/// expected to perform conversions to the format requested by their
/// device.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum Color {
    RGBA(f64, f64, f64, f64, f64)
}

/// Representation of an object in JSON. It is often (albeit not
/// always) possible to choose a more precise data structure for
/// representing values send/accepted by a service. If possible,
/// adapters should rather pick such more precise data structure.
#[derive(Debug, Clone, PartialEq)]
pub struct Json(serde_json::value::Value);

impl PartialOrd for Json {
    /// Two Json objects are never comparable to each other.
    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
        None
    }
}

/// Base definitions for actual values. Most API clients will rather
/// use `Value`.
///
/// Splitting the defintion between `Value` and `ValueBase` is mostly
/// a convenience to refine the automatically-derived `PartialOrd` on
/// `ValueBase` into something that will never compare two values with
/// different types.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum ValueBase {
    Unit,
    Bool(bool),
    Duration(Duration),
    TimeStamp(chrono::DateTime<Local>),
    Temperature(Temperature),
    Color(Color),

    // FIXME: Add more as we identify needs
    Json(Json),
    Binary {data: Vec<u8>, mimetype: String}
}

impl ValueBase {
    pub fn get_type(&self) -> Type {
        match *self {
            ValueBase::Unit => Type::Unit,
            ValueBase::Bool(_) => Type::Bool,
            ValueBase::Duration(_) => Type::Duration,
            ValueBase::TimeStamp(_) => Type::TimeStamp,
            ValueBase::Temperature(_) => Type::Temperature,
            ValueBase::Color(_) => Type::Color,
            ValueBase::Json(_) => Type::Json,
            ValueBase::Binary{..} => Type::Binary,
        }
    }
}

/// Representation of an actual value that can be sent to/received
/// from a service.
#[derive(Debug, Clone, PartialEq)]
pub struct Value(ValueBase);

impl Value {
    /// Get the type attached to a value.
    pub fn get_type(&self) -> Type {
        self.0.get_type()
    }
}

impl PartialOrd for Value {
    /// Two values of the same type can be compared using the usual
    /// comparison for values of this type. Two values of distinct
    /// types cannot be compared.
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.get_type() != other.get_type() {
            None
        } else {
            self.0.partial_cmp(&other.0)
        }
    }
}
<commit_msg>Adding ExtNumeric<commit_after>//!
//! Values manipulated by endpoints
//!

use std::time::Duration;
use std::cmp::{PartialOrd, Ordering};

extern crate chrono;
use self::chrono::{DateTime, Local};

extern crate serde_json;

///
/// The type of values manipulated by endpoints.
///
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub enum Type {
    ///
    /// # Trivial values
    ///

    /// An empty value. Used for instance to inform that a countdown
    /// has reached 0 or that a device is ready.
    Unit,

    /// A boolean. Used for instance for on-off switches, presence
    /// detectors, etc.
    Bool,

    ///
    /// # Time
    ///

    /// A duration. Used for instance in countdowns.
    Duration,

    /// A precise timestamp. Used for instance to determine when an
    /// event has taken place.
    TimeStamp,

    Temperature,

    ///
    /// ...
    ///
    Color,
    Json,
    Binary,
    ExtNumeric,
}

/// A temperature. Internal representation may be either Fahrenheit or
/// Celcius. The FoxBox adapters are expected to perform conversions
/// to the format requested by their devices.
#[derive(Debug, Clone, PartialEq)]
pub enum Temperature {
    /// Fahrenheit
    F(f64),
    /// Celcius
    C(f64),
}

impl Temperature {
    /// Get a temperature in Fahrenheit.
    pub fn as_f(&self) -> f64 {
        unimplemented!();
    }

    /// Get a temperature in Celcius.
    pub fn as_c(&self) -> f64 {
        unimplemented!();
    }
}

impl PartialOrd for Temperature {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.as_c().partial_cmp(&other.as_c())
    }
}

/// A color. Internal representation may vary. The FoxBox adapters are
/// expected to perform conversions to the format requested by their
/// device.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum Color {
    RGBA(f64, f64, f64, f64, f64)
}

/// Representation of an object in JSON. It is often (albeit not
/// always) possible to choose a more precise data structure for
/// representing values send/accepted by a service. If possible,
/// adapters should rather pick such more precise data structure.
#[derive(Debug, Clone, PartialEq)]
pub struct Json(serde_json::value::Value);

impl PartialOrd for Json {
    /// Two Json objects are never comparable to each other.
    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
        None
    }
}

/// A data structure holding a numeric value of a type that has not
/// been standardized yet.
#[derive(Debug, Clone, PartialEq)]
pub struct ExtNumeric {
    value: f64,

    /// The vendor. Used for namespacing purposes, to avoid
    /// confusing two incompatible extensions with similar
    /// names. For instance, "foxlink@mozilla.com".
    vendor: String,

    /// Identification of the adapter introducing this value.
    /// Designed to aid with tracing and debugging.
    adapter: String,

    /// A string describing the nature of the value, designed to
    /// aid with type-checking.
    ///
    /// Examples: `"GroundHumidity"`.
    kind: String,
}

impl PartialOrd for ExtNumeric {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.vendor != other.vendor {
            return None;
        } else if self.kind != other.kind {
            return None;
        } else {
            self.value.partial_cmp(&other.value)
        }
    }
}

/// Base definitions for actual values. Most API clients will rather
/// use `Value`.
///
/// Splitting the defintion between `Value` and `ValueBase` is mostly
/// a convenience to refine the automatically-derived `PartialOrd` on
/// `ValueBase` into something that will never compare two values with
/// different types.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum ValueBase {
    Unit,
    Bool(bool),
    Duration(Duration),
    TimeStamp(chrono::DateTime<Local>),
    Temperature(Temperature),
    Color(Color),

    // FIXME: Add more as we identify needs

    /// A numeric value representing a unit that has not been
    /// standardized yet into the API.
    ExtNumeric(ExtNumeric),
    Json(Json),
    Binary {data: Vec<u8>, mimetype: String}
}

impl ValueBase {
    pub fn get_type(&self) -> Type {
        match *self {
            ValueBase::Unit => Type::Unit,
            ValueBase::Bool(_) => Type::Bool,
            ValueBase::Duration(_) => Type::Duration,
            ValueBase::TimeStamp(_) => Type::TimeStamp,
            ValueBase::Temperature(_) => Type::Temperature,
            ValueBase::Color(_) => Type::Color,
            ValueBase::Json(_) => Type::Json,
            ValueBase::Binary{..} => Type::Binary,
            ValueBase::ExtNumeric(_) => Type::ExtNumeric,
        }
    }
}

/// Representation of an actual value that can be sent to/received
/// from a service.
#[derive(Debug, Clone, PartialEq)]
pub struct Value(ValueBase);

impl Value {
    /// Get the type attached to a value.
    pub fn get_type(&self) -> Type {
        self.0.get_type()
    }
}

impl PartialOrd for Value {
    /// Two values of the same type can be compared using the usual
    /// comparison for values of this type. Two values of distinct
    /// types cannot be compared.
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.get_type() != other.get_type() {
            None
        } else {
            self.0.partial_cmp(&other.0)
        }
    }
}
<|endoftext|>