<commit_before>use alloc::heap;
use std::marker::PhantomData;
use std::mem;
use std::slice;

use common::constant::VECTOR_SIZE;
use common::err::*;
use common::StringSlice;
use exec::Executor;
use io::stream::*;
use schema::Schema;
use rows::RowBlock;
use types::*;

const BUF_SIZE: usize = 65536;

pub struct DelimTextScanner<'a> {
  data_schema : Schema,
  read_fields : Option<Schema>,
  line_delim  : u8,
  field_delim : u8,
  reader      : Box<StreamReader>,
  marker      : PhantomData<&'a ()>,

  // variable
  readbuf_ptr: *mut u8,
  read_line_num: usize,
  line_slices_ptr: *mut StringSlice,
  line_slices: &'a mut [StringSlice],
  last_read_len: usize,
  should_parse_line: bool,
}

impl<'a> DelimTextScanner<'a> {
  pub fn new(
        data_schema: Schema,
        read_fields: Option<Schema>,
        stream: Box<StreamReader>,
        field_delim: u8) -> DelimTextScanner<'a> {

    let mut line_slices_ptr = unsafe {
      heap::allocate(mem::size_of::<StringSlice>() * 1024, mem::min_align_of::<StringSlice>())
    } as *mut StringSlice;

    let mut line_slices: &mut [StringSlice] = unsafe {
      slice::from_raw_parts_mut(line_slices_ptr as *mut StringSlice, 1024)
    };

    DelimTextScanner {
      data_schema: data_schema,
      read_fields: read_fields,

      line_delim: '\n' as u8,
      field_delim: field_delim,

      reader: stream,
      marker: PhantomData,

      readbuf_ptr: unsafe { heap::allocate(BUF_SIZE, 16) },
      read_line_num: 0,
      line_slices_ptr: line_slices_ptr,
      line_slices: line_slices,
      last_read_len: 0,
      should_parse_line: true
    }
  }

  fn read_line_num(&self) -> usize {
    self.read_line_num
  }

  fn line_slices(&self) -> &[StringSlice] {
    self.line_slices
  }

  fn find_first_record_index(&self, bytes: &[u8]) -> Option<usize> {
    //let bytes : &[u8] = unsafe { mem::transmute(text) };

    let mut pos : usize = 0;
    let mut found : bool = false;

    for c in bytes {
      if self.line_delim == *c {
        found = true;
        break;
      }

      pos = pos + 1;
    }

    match found {
      true => Some(pos + 1),
      false => None
    }
  }

  /// Return the last index of fields, which will be used for the following call.
  /// It will return a tuple consisting of found line number and last delim index.
  fn read_line_batch(&mut self) -> usize {

    self.read_line_num      = 0; // read line counter
    let mut last_pos: usize = 0; // keep the start offset
    let mut cur_pos : usize = 0; // the current offset

    while (cur_pos < BUF_SIZE && self.read_line_num < VECTOR_SIZE) {
      // for each character
      let c: u8  = unsafe { *self.readbuf_ptr.offset(cur_pos as isize) };

      // check if the character is line delimiter
      if c == self.line_delim {

        // if found, set each StringSlice with the start offset and the current position
        self.line_slices[self.read_line_num].set_ptr(unsafe {self.readbuf_ptr.offset(last_pos as isize)});
        self.line_slices[self.read_line_num].set_len((cur_pos - last_pos) as i32);

        last_pos = cur_pos + 1; // to skip the delimiter character
        self.read_line_num = self.read_line_num + 1; // increase the line number
      }

      cur_pos = cur_pos + 1;
    }

    (last_pos - 1)
  }
}

impl<'a> Executor for DelimTextScanner<'a> {

  fn init(&mut self) -> Void {
    self.reader.read(
      unsafe {slice::from_raw_parts_mut(self.readbuf_ptr, BUF_SIZE)}
    );

    void_ok()
  }

  fn next(&mut self, rowblock: &mut RowBlock) -> Void {

    let mut row_idx: usize = 0;
    let mut r: usize;
    loop {

      if self.should_parse_line {
        r = self.read_line_batch();
      }

      if self.last_read_len < 1 || row_idx >= VECTOR_SIZE {
        break;
      }
    }

    void_ok()
  }

  fn close(&mut self) -> Void {
    void_ok()
  }

  fn in_schema(&self) -> &Schema {
    &self.data_schema
  }

  fn out_schema(&self) -> &Schema {
    match self.read_fields {
      Some(ref s) => s,
      None => &self.data_schema
    }
  }
}

#[test]
fn test_find_first_record_index() {
  let mut s = Schema::new();
  s.add_column("c1", *TEXT_TY);
  s.add_column("c2", *TEXT_TY);

  let fin = Box::new(FileInputStream::new("/home/hyunsik/tpch/lineitem/lineitem.tbl".to_string()));
  let s = DelimTextScanner::new(s, None, fin, '\n' as u8);

  assert_eq!(4, s.find_first_record_index("abc\nbb".as_bytes()).unwrap());
  assert_eq!(1, s.find_first_record_index("\nabc\nbb".as_bytes()).unwrap());
  assert_eq!(2, s.find_first_record_index("\r\nabc\nbb".as_bytes()).unwrap());
  assert!(s.find_first_record_index("aaaaabcabbb".as_bytes()).is_none());

}

#[test]
fn test_str_array() {
  let a: [&str;1024];

  //let mut slices: Vec<&str> = Vec::with_capacity(12);
  //unsafe { slices.set_len(12) };
  //slices.get_unchecked_mut(x)
  //slices[1] = "abc";

  let mut ptr: *mut &str = unsafe {
    heap::allocate(
      mem::size_of::<&str>() * 1024,
      mem::min_align_of::<&str>()
    ) as *mut &str
  };

  let mut slices: &mut [&str] = unsafe {
    slice::from_raw_parts_mut(ptr as *mut &str, 1024)
  };

  slices[0] = "abc";

  //slices[0] = "abc";
}

#[test]
fn test_next_line_indxes() {
  let mut schema = Schema::new();
  schema.add_column("c1", *TEXT_TY);
  schema.add_column("c2", *TEXT_TY);

  let mut fin = Box::new(FileInputStream::new("/Users/hyunsik/tpch/lineitem/lineitem.tbl".to_string()));
  assert!(fin.open().is_ok());
  let mut s = DelimTextScanner::new(schema, None, fin, '\n' as u8);
  assert!(s.init().is_ok());
  let res = s.read_line_batch();

  for x in 0..s.read_line_num() {
    println!("{}", s.line_slices()[x]);
  }
}
  // let mut delim_indexes:Vec<usize> = Vec::new();
  // let r1 =
  //   s.next_line_indexes("abc\nbb\nabcdef\nabcd".as_ptr(), &mut delim_indexes);
  // assert_eq!(3, r1.0);
  // assert_eq!(13, r1.1);

//   delim_indexes.clear();

//   let r2 =
//     s.next_line_indexes("a\nb\nabcde\n".as_ptr(), &mut delim_indexes);
//   assert_eq!(3, r2.0);
//   assert_eq!(9, r2.1);
// }<commit_msg>Implement DelimTextParser::parse_fields.<commit_after>///
///
///

use alloc::heap;
use std::marker::PhantomData;
use std::mem;
use std::slice;

use common::constant::VECTOR_SIZE;
use common::err::*;
use common::StringSlice;
use exec::Executor;
use io::stream::*;
use schema::Schema;
use rows::RowBlock;
use types::*;

const BUF_SIZE: usize = 65536;

pub struct DelimTextScanner<'a> {
  data_schema : Schema,
  read_fields : Option<Schema>,
  line_delim  : u8,
  field_delim : u8,
  reader      : Box<StreamReader>,
  marker      : PhantomData<&'a ()>,

  // variable
  readbuf_ptr: *mut u8,
  should_parse_line: bool, // parse lines from read buffer
  read_line_num: usize,    // number of read lines for each next
  line_slices_ptr: *mut StringSlice,
  line_slices: &'a mut [StringSlice],
  fields_slices_ptr: *mut StringSlice,
  fields_slices: &'a mut [StringSlice],
  last_read_len: usize,

}

impl<'a> DelimTextScanner<'a> {
  pub fn new(
        data_schema: Schema,
        read_fields: Option<Schema>,
        stream: Box<StreamReader>,
        field_delim: u8) -> DelimTextScanner<'a> {

    let mut line_slices_ptr = unsafe {
      heap::allocate(mem::size_of::<StringSlice>() * 1024, mem::min_align_of::<StringSlice>())
    } as *mut StringSlice;

    let mut line_slices: &mut [StringSlice] = unsafe {
      slice::from_raw_parts_mut(line_slices_ptr as *mut StringSlice, 1024)
    };

    let mut fields_slices_ptr = unsafe {
      heap::allocate(
        mem::size_of::<StringSlice>() * data_schema.size(),
        mem::min_align_of::<StringSlice>()
      )
    } as *mut StringSlice;

    let mut fields_slices: &mut [StringSlice] = unsafe {
      slice::from_raw_parts_mut(fields_slices_ptr as *mut StringSlice, data_schema.size())
    };

    DelimTextScanner {
      data_schema: data_schema,
      read_fields: read_fields,

      line_delim: '\n' as u8,
      field_delim: field_delim,

      reader: stream,
      marker: PhantomData,

      readbuf_ptr: unsafe { heap::allocate(BUF_SIZE, 16) },
      should_parse_line: true,
      read_line_num: 0,
      line_slices_ptr: line_slices_ptr,
      line_slices: line_slices,
      fields_slices_ptr: fields_slices_ptr,
      fields_slices: fields_slices,
      last_read_len: 0
    }
  }

  fn read_line_num(&self) -> usize {
    self.read_line_num
  }

  fn line_slices(&self) -> &[StringSlice] {
    self.line_slices
  }

  fn find_first_record_index(&self, bytes: &[u8]) -> Option<usize> {
    //let bytes : &[u8] = unsafe { mem::transmute(text) };

    let mut pos : usize = 0;
    let mut found : bool = false;

    for c in bytes {
      if self.line_delim == *c {
        found = true;
        break;
      }

      pos = pos + 1;
    }

    match found {
      true => Some(pos + 1),
      false => None
    }
  }

  /// Return the last index of fields, which will be used for the following call.
  /// It will return a tuple consisting of found line number and last delim index.
  fn read_line_batch(&mut self) -> usize {

    self.read_line_num      = 0; // read line counter
    let mut last_pos: usize = 0; // keep the start offset
    let mut cur_pos : usize = 0; // the current offset

    while (cur_pos < BUF_SIZE && self.read_line_num < VECTOR_SIZE) {
      // for each character
      let c: u8  = unsafe { *self.readbuf_ptr.offset(cur_pos as isize) };

      // check if the character is line delimiter
      if c == self.line_delim {

        // if found, set each StringSlice with the start offset and the current position
        self.line_slices[self.read_line_num].set_ptr(unsafe {self.readbuf_ptr.offset(last_pos as isize)});
        self.line_slices[self.read_line_num].set_len((cur_pos - last_pos) as i32);

        last_pos = cur_pos + 1; // to skip the delimiter character
        self.read_line_num = self.read_line_num + 1; // increase the line number
      }

      cur_pos = cur_pos + 1;
    }

    (last_pos - 1)
  }

  #[inline]
  fn parse_fields(&mut self, line_idx: usize) {
    let mut last_pos: usize = 0; // keep the start offset
    let mut cur_pos : usize = 0; // the current offset
    let mut field_idx: usize = 0;

    let slice = self.line_slices[line_idx];
    let line_len = slice.len() as usize;

    while (cur_pos < line_len && field_idx < self.data_schema.size()) {
      let c: u8 = unsafe { *slice.as_ptr().offset(cur_pos as isize) };

      // check if the character is line delimiter
      if c == self.field_delim {
        self.fields_slices[field_idx].set_ptr(unsafe {slice.as_ptr().offset(last_pos as isize)});
        self.fields_slices[field_idx].set_len((cur_pos - last_pos) as i32);

        last_pos = cur_pos + 1;
        field_idx = field_idx + 1;
      }

      cur_pos = cur_pos + 1;
    }
  }

  fn fill_vector() {

  }
}

impl<'a> Executor for DelimTextScanner<'a> {

  fn init(&mut self) -> Void {
    self.reader.read(
      unsafe {slice::from_raw_parts_mut(self.readbuf_ptr, BUF_SIZE)}
    );

    void_ok()
  }

  fn next(&mut self, rowblock: &mut RowBlock) -> Void {

    let mut row_idx: usize = 0;
    let mut r: usize;
    loop {

      if self.should_parse_line {
        r = self.read_line_batch();
      }

      // self.reader.read(
      //   unsafe {slice::from_raw_parts_mut(self.readbuf_ptr, BUF_SIZE)}
      // );
    }

    void_ok()
  }

  fn close(&mut self) -> Void {
    void_ok()
  }

  fn in_schema(&self) -> &Schema {
    &self.data_schema
  }

  fn out_schema(&self) -> &Schema {
    match self.read_fields {
      Some(ref s) => s,
      None => &self.data_schema
    }
  }
}

#[test]
fn test_find_first_record_index() {
  let mut s = Schema::new();
  s.add_column("c1", *TEXT_TY);
  s.add_column("c2", *TEXT_TY);

  let fin = Box::new(FileInputStream::new("/home/hyunsik/tpch/lineitem/lineitem.tbl".to_string()));
  let s = DelimTextScanner::new(s, None, fin, '\n' as u8);

  assert_eq!(4, s.find_first_record_index("abc\nbb".as_bytes()).unwrap());
  assert_eq!(1, s.find_first_record_index("\nabc\nbb".as_bytes()).unwrap());
  assert_eq!(2, s.find_first_record_index("\r\nabc\nbb".as_bytes()).unwrap());
  assert!(s.find_first_record_index("aaaaabcabbb".as_bytes()).is_none());

}

#[test]
fn test_str_array() {
  let a: [&str;1024];

  //let mut slices: Vec<&str> = Vec::with_capacity(12);
  //unsafe { slices.set_len(12) };
  //slices.get_unchecked_mut(x)
  //slices[1] = "abc";

  let mut ptr: *mut &str = unsafe {
    heap::allocate(
      mem::size_of::<&str>() * 1024,
      mem::min_align_of::<&str>()
    ) as *mut &str
  };

  let mut slices: &mut [&str] = unsafe {
    slice::from_raw_parts_mut(ptr as *mut &str, 1024)
  };

  slices[0] = "abc";

  //slices[0] = "abc";
}

#[test]
fn test_read_line_batch() {
  let mut schema = Schema::new();
  schema.add_column("c1", *TEXT_TY);
  schema.add_column("c2", *TEXT_TY);

  let mut fin = Box::new(FileInputStream::new("/Users/hyunsik/tpch/lineitem/lineitem.tbl".to_string()));
  assert!(fin.open().is_ok());
  let mut s = DelimTextScanner::new(schema, None, fin, '\n' as u8);
  assert!(s.init().is_ok());
  let res = s.read_line_batch();
}
  // let mut delim_indexes:Vec<usize> = Vec::new();
  // let r1 =
  //   s.next_line_indexes("abc\nbb\nabcdef\nabcd".as_ptr(), &mut delim_indexes);
  // assert_eq!(3, r1.0);
  // assert_eq!(13, r1.1);

//   delim_indexes.clear();

//   let r2 =
//     s.next_line_indexes("a\nb\nabcde\n".as_ptr(), &mut delim_indexes);
//   assert_eq!(3, r2.0);
//   assert_eq!(9, r2.1);
// }<|endoftext|>


<commit_before>// Copyright (c) 2017-2021 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use core::convert::Infallible;
use std::time::Duration;

use embedded_hal::digital::blocking::{
    InputPin as InputPinHal, StatefulOutputPin as StatefulOutputPinHal,
    ToggleableOutputPin as ToggleableOutputPinHal,
};
use embedded_hal::pwm::blocking::Pwm as PwmHal;

use super::{InputPin, IoPin, OutputPin, Pin};

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for Pin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for InputPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for IoPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for OutputPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `StatefulOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::StatefulOutputPin for IoPin {
    fn is_set_high(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_high(self)
    }

    fn is_set_low(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_low(self)
    }
}

/// Unproven `StatefulOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::StatefulOutputPin for OutputPin {
    fn is_set_high(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_high(self)
    }

    fn is_set_low(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_low(self)
    }
}

/// Unproven `ToggleableOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::ToggleableOutputPin for IoPin {
    type Error = Infallible;

    fn toggle(&mut self) -> Result<(), Self::Error> {
        ToggleableOutputPinHal::toggle(self)
    }
}

/// Unproven `ToggleableOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::ToggleableOutputPin for OutputPin {
    type Error = Infallible;

    fn toggle(&mut self) -> Result<(), Self::Error> {
        ToggleableOutputPinHal::toggle(self)
    }
}

/// Unproven `Pwm` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::Pwm for OutputPin {
    type Duty = f64;
    type Channel = ();
    type Time = Duration;

    /// Disables a PWM `channel`.
    fn disable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::disable(self, &channel);
    }

    /// Enables a PWM `channel`.
    fn enable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::enable(self, &channel);
    }

    /// Returns the current PWM period.
    fn get_period(&self) -> Self::Time {
        PwmHal::get_period(self).unwrap_or_default()
    }

    /// Returns the current duty cycle.
    fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
        PwmHal::get_duty(self, &channel).unwrap_or_default()
    }

    /// Returns the maximum duty cycle value.
    fn get_max_duty(&self) -> Self::Duty {
        PwmHal::get_max_duty(self).unwrap_or(1.0)
    }

    /// Sets a new duty cycle.
    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
        let _ = PwmHal::set_duty(self, &channel, duty);
    }

    /// Sets a new PWM period.
    fn set_period<P>(&mut self, period: P)
    where
        P: Into<Self::Time>,
    {
        let _ = PwmHal::set_period(self, period);
    }
}

/// Unproven `Pwm` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::Pwm for IoPin {
    type Duty = f64;
    type Channel = ();
    type Time = Duration;

    /// Disables a PWM `channel`.
    fn disable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::disable(self, &channel);
    }

    /// Enables a PWM `channel`.
    fn enable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::enable(self, &channel);
    }

    /// Returns the current PWM period.
    fn get_period(&self) -> Self::Time {
        PwmHal::get_period(self).unwrap_or_default()
    }

    /// Returns the current duty cycle.
    fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
        PwmHal::get_duty(self, &channel).unwrap_or_default()
    }

    /// Returns the maximum duty cycle value.
    fn get_max_duty(&self) -> Self::Duty {
        PwmHal::get_max_duty(self).unwrap_or(1.0)
    }

    /// Sets a new duty cycle.
    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
        let _ = PwmHal::set_duty(self, &channel, duty);
    }

    /// Sets a new PWM period.
    fn set_period<P>(&mut self, period: P)
    where
        P: Into<Self::Time>,
    {
        let _ = PwmHal::set_period(self, period);
    }
}
<commit_msg>HAL IoPin trait implementation<commit_after>// Copyright (c) 2017-2021 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use core::convert::Infallible;
use std::time::Duration;

use embedded_hal::digital::blocking::{
    InputPin as InputPinHal, StatefulOutputPin as StatefulOutputPinHal,
    ToggleableOutputPin as ToggleableOutputPinHal,
};
use embedded_hal::pwm::blocking::Pwm as PwmHal;

use super::{InputPin, IoPin, OutputPin, Pin};
use crate::gpio::Mode;

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for Pin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for InputPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for IoPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for OutputPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `StatefulOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::StatefulOutputPin for IoPin {
    fn is_set_high(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_high(self)
    }

    fn is_set_low(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_low(self)
    }
}

/// Unproven `StatefulOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::StatefulOutputPin for OutputPin {
    fn is_set_high(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_high(self)
    }

    fn is_set_low(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_low(self)
    }
}

/// Unproven `ToggleableOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::ToggleableOutputPin for IoPin {
    type Error = Infallible;

    fn toggle(&mut self) -> Result<(), Self::Error> {
        ToggleableOutputPinHal::toggle(self)
    }
}

/// Unproven `ToggleableOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::ToggleableOutputPin for OutputPin {
    type Error = Infallible;

    fn toggle(&mut self) -> Result<(), Self::Error> {
        ToggleableOutputPinHal::toggle(self)
    }
}

/// Unproven `Pwm` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::Pwm for OutputPin {
    type Duty = f64;
    type Channel = ();
    type Time = Duration;

    /// Disables a PWM `channel`.
    fn disable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::disable(self, &channel);
    }

    /// Enables a PWM `channel`.
    fn enable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::enable(self, &channel);
    }

    /// Returns the current PWM period.
    fn get_period(&self) -> Self::Time {
        PwmHal::get_period(self).unwrap_or_default()
    }

    /// Returns the current duty cycle.
    fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
        PwmHal::get_duty(self, &channel).unwrap_or_default()
    }

    /// Returns the maximum duty cycle value.
    fn get_max_duty(&self) -> Self::Duty {
        PwmHal::get_max_duty(self).unwrap_or(1.0)
    }

    /// Sets a new duty cycle.
    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
        let _ = PwmHal::set_duty(self, &channel, duty);
    }

    /// Sets a new PWM period.
    fn set_period<P>(&mut self, period: P)
    where
        P: Into<Self::Time>,
    {
        let _ = PwmHal::set_period(self, period);
    }
}

/// Unproven `Pwm` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::Pwm for IoPin {
    type Duty = f64;
    type Channel = ();
    type Time = Duration;

    /// Disables a PWM `channel`.
    fn disable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::disable(self, &channel);
    }

    /// Enables a PWM `channel`.
    fn enable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::enable(self, &channel);
    }

    /// Returns the current PWM period.
    fn get_period(&self) -> Self::Time {
        PwmHal::get_period(self).unwrap_or_default()
    }

    /// Returns the current duty cycle.
    fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
        PwmHal::get_duty(self, &channel).unwrap_or_default()
    }

    /// Returns the maximum duty cycle value.
    fn get_max_duty(&self) -> Self::Duty {
        PwmHal::get_max_duty(self).unwrap_or(1.0)
    }

    /// Sets a new duty cycle.
    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
        let _ = PwmHal::set_duty(self, &channel, duty);
    }

    /// Sets a new PWM period.
    fn set_period<P>(&mut self, period: P)
    where
        P: Into<Self::Time>,
    {
        let _ = PwmHal::set_period(self, period);
    }
}

/// Unproven `IoPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::IoPin<IoPin, IoPin> for IoPin {

    type Error = Infallible;

    /// Tries to convert this pin to input mode.
    ///
    /// If the pin is already in input mode, this method should succeed.
    fn into_input_pin(mut self) -> Result<IoPin, Self::Error> {
        let now_mode = self.mode();
        return if now_mode == Mode::Input {
            Ok(self)
        } else {
            self.set_mode(Mode::Input);
            Ok(self)
        };
    }

    /// Tries to convert this pin to output mode with the given initial state.
    ///
    /// If the pin is already in the requested state, this method should
    /// succeed.
    fn into_output_pin(mut self, state: embedded_hal_0::digital::v2::PinState) -> Result<IoPin, Self::Error> {
        let now_mode = self.mode();

        return if now_mode == Mode::Output {
            Ok(self)
        } else {
            self.set_mode(Mode::Output);
            match state {
                embedded_hal_0::digital::v2::PinState::Low => self.set_low() ,
                embedded_hal_0::digital::v2::PinState::High => self.set_high()
            }
            Ok(self)
        };
    }
}
<|endoftext|>


<commit_before>use std::str::from_utf8;
use nom::IResult;

#[derive(Debug,PartialEq,Eq)]
pub struct PosixHeader<'a> {
    pub name:     & 'a str,
    pub mode:     & 'a str,
    pub uid:      u64,
    pub gid:      u64,
    pub size:     u64,
    pub mtime:    u64,
    pub chksum:   & 'a str,
    pub typeflag: char, /* TODO: enum */
    pub linkname: & 'a str,
    pub ustar:    Option<UStarHeader<'a>>
}

#[derive(Debug,PartialEq,Eq)]
pub struct UStarHeader<'a> {
    pub magic:    & 'a str,
    pub version:  & 'a str,
    pub uname:    & 'a str,
    pub gname:    & 'a str,
    pub devmajor: & 'a str,
    pub devminor: & 'a str,
    pub prefix:   & 'a str,
}

#[derive(Debug,PartialEq,Eq)]
pub struct TarEntry<'a> {
    pub header:   PosixHeader<'a>,
    pub contents: & 'a str
}

/* TODO: validation */
fn str_to_u64(s: &str, base: u64) -> u64 {
    let mut u = 0;
    let mut f = 1;

    for c in s.chars().rev().skip_while(|&c| c == '\0') {
        u += f * ((c as u64) - ('0' as u64));
        f *= base;
    }

    u
}

pub fn octal_to_u64(o: &str) -> u64 {
    str_to_u64(o, 8)
}

fn parse_ustar(i: &[u8]) -> IResult<&[u8], Option<UStarHeader>> {
    chain!(i,
        magic:    take_str!(6)  ~
        version:  take_str!(2)  ~
        uname:    take_str!(32) ~
        gname:    take_str!(32) ~
        devmajor: take_str!(8)  ~
        devminor: take_str!(8)  ~
        prefix:   take_str!(155),
        ||{
            match magic {
                "ustar\0" => Some(UStarHeader {
                    magic:    magic,
                    version:  version,
                    uname:    uname,
                    gname:    gname,
                    devmajor: devmajor,
                    devminor: devminor,
                    prefix:   prefix
                }),
                _ => None,
            }
        }
    )
}

fn parse_header(i: &[u8]) -> IResult<&[u8], PosixHeader> {
    chain!(i,
        name:     take_str!(100) ~
        mode:     take_str!(8)   ~
        uid:      take_str!(8)   ~
        gid:      take_str!(8)   ~
        size:     take_str!(12)  ~
        mtime:    take_str!(12)  ~
        chksum:   take_str!(8)   ~
        typeflag: take!(1)       ~
        linkname: take_str!(100) ~
        ustar:    parse_ustar    ~
        take!(12), /* padding to 512 */
        ||{
            PosixHeader {
                name:     name,
                mode:     mode,
                uid:      octal_to_u64(uid),
                gid:      octal_to_u64(gid),
                size:     octal_to_u64(size),
                mtime:    octal_to_u64(mtime), /* TODO: u64 */
                chksum:   chksum,
                typeflag: typeflag[0] as char,
                linkname: linkname,
                ustar:    ustar
            }
        }
    )
}

fn parse_contents(i: &[u8], size: u64) -> IResult<&[u8], &str> {
    let trailing = size % 512;
    let padding = match trailing {
        0 => 0,
        t => 512 - t
    };
    chain!(i,
        contents: take_str!(size as usize) ~
        take!(padding as usize),
        ||{
            contents
        }
    )
}

fn parse_entry(i: &[u8]) -> IResult<&[u8], TarEntry> {
    chain!(i,
        header:   parse_header ~
        contents: apply!(parse_contents, header.size),
        ||{
            TarEntry {
                header: header,
                contents: contents
            }
        }
    )
}

pub fn parse_tar(i: &[u8]) -> IResult<&[u8], Vec<TarEntry>> {
    many0!(i, parse_entry)
}

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

    #[test]
    fn octal_to_u64_test() {
        match octal_to_u64("756") {
            494 => {},
            o => panic!("octal_to_u64 failed, expected 494 but got {}", o)
        }
        match octal_to_u64("") {
            0 => {},
            o => panic!("octal_to_u64 failed, expected 0 but got {}", o)
        }
    }
}
<commit_msg>rework ustar parsing<commit_after>use std::str::from_utf8;
use nom::IResult;

#[derive(Debug,PartialEq,Eq)]
pub struct PosixHeader<'a> {
    pub name:     & 'a str,
    pub mode:     & 'a str,
    pub uid:      u64,
    pub gid:      u64,
    pub size:     u64,
    pub mtime:    u64,
    pub chksum:   & 'a str,
    pub typeflag: char, /* TODO: enum */
    pub linkname: & 'a str,
    pub ustar:    Option<UStarHeader<'a>>
}

#[derive(Debug,PartialEq,Eq)]
pub struct UStarHeader<'a> {
    pub magic:    & 'a str,
    pub version:  & 'a str,
    pub uname:    & 'a str,
    pub gname:    & 'a str,
    pub devmajor: & 'a str,
    pub devminor: & 'a str,
    pub prefix:   & 'a str,
}

#[derive(Debug,PartialEq,Eq)]
pub struct TarEntry<'a> {
    pub header:   PosixHeader<'a>,
    pub contents: & 'a str
}

/* TODO: validation */
fn str_to_u64(s: &str, base: u64) -> u64 {
    let mut u = 0;
    let mut f = 1;

    for c in s.chars().rev().skip_while(|&c| c == '\0') {
        u += f * ((c as u64) - ('0' as u64));
        f *= base;
    }

    u
}

pub fn octal_to_u64(o: &str) -> u64 {
    str_to_u64(o, 8)
}

fn parse_ustar(i: &[u8]) -> IResult<&[u8], Option<UStarHeader>> {
    chain!(i,
        tag!("ustar\0")          ~
        version:  take_str!(2)   ~
        uname:    take_str!(32)  ~
        gname:    take_str!(32)  ~
        devmajor: take_str!(8)   ~
        devminor: take_str!(8)   ~
        prefix:   take_str!(155) ~
        take!(12), /* padding to 512 */
        ||{
            Some(UStarHeader {
                magic:    "ustar\0",
                version:  version,
                uname:    uname,
                gname:    gname,
                devmajor: devmajor,
                devminor: devminor,
                prefix:   prefix
            })
        }
    )
}

fn parse_posix(i: &[u8]) -> IResult<&[u8], Option<UStarHeader>> {
    chain!(i,
        take!(255), /* padding to 512 */
        ||{
            None
        }
    )
}

fn parse_header(i: &[u8]) -> IResult<&[u8], PosixHeader> {
    chain!(i,
        name:     take_str!(100) ~
        mode:     take_str!(8)   ~
        uid:      take_str!(8)   ~
        gid:      take_str!(8)   ~
        size:     take_str!(12)  ~
        mtime:    take_str!(12)  ~
        chksum:   take_str!(8)   ~
        typeflag: take!(1)       ~
        linkname: take_str!(100) ~
        ustar:    alt!(parse_ustar | parse_posix),
        ||{
            PosixHeader {
                name:     name,
                mode:     mode,
                uid:      octal_to_u64(uid),
                gid:      octal_to_u64(gid),
                size:     octal_to_u64(size),
                mtime:    octal_to_u64(mtime),
                chksum:   chksum,
                typeflag: typeflag[0] as char,
                linkname: linkname,
                ustar:    ustar
            }
        }
    )
}

fn parse_contents(i: &[u8], size: u64) -> IResult<&[u8], &str> {
    let trailing = size % 512;
    let padding = match trailing {
        0 => 0,
        t => 512 - t
    };
    chain!(i,
        contents: take_str!(size as usize) ~
        take!(padding as usize),
        ||{
            contents
        }
    )
}

fn parse_entry(i: &[u8]) -> IResult<&[u8], TarEntry> {
    chain!(i,
        header:   parse_header ~
        contents: apply!(parse_contents, header.size),
        ||{
            TarEntry {
                header: header,
                contents: contents
            }
        }
    )
}

pub fn parse_tar(i: &[u8]) -> IResult<&[u8], Vec<TarEntry>> {
    many0!(i, parse_entry)
}

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

    #[test]
    fn octal_to_u64_test() {
        match octal_to_u64("756") {
            494 => {},
            o => panic!("octal_to_u64 failed, expected 494 but got {}", o)
        }
        match octal_to_u64("") {
            0 => {},
            o => panic!("octal_to_u64 failed, expected 0 but got {}", o)
        }
    }
}
<|endoftext|>


<commit_before>use expr::{Expr, Op};

#[derive(Clone, Debug, PartialEq)]
enum Token {
  Plus,
  Integer(i64),
}

struct Lexer {
  text: String,
  pos: i64,
}

impl Lexer {
  pub fn new(text: String) -> Lexer {
    Lexer { text: text, pos: 0 }
  }

  fn remove_first(&mut self, n: usize) {
    let t = self.text.clone();
    let (old, remainder) = t.split_at(n);
    self.text = remainder.to_string();
  }

  pub fn integer(&mut self) -> Option<Token> {
    let int_str: String = self.text
      .chars()
      .take_while(|c| c.is_digit(10))
      .collect();

    match int_str.parse::<i64>() {
      Ok(n) => {
        self.remove_first(int_str.len());
        return Some(Token::Integer(n));
      }
      Err(e) => {
        println!("---------------{:?}", e);
        panic!();
      }
    }

    None
  }

  pub fn plus(&mut self) -> Option<Token> {
    if self.text.starts_with('+') {
      self.remove_first(1);
      return Some(Token::Plus);
    } else {
      panic!();
    }
  }

  pub fn get_next_token(&mut self) -> Option<Token> {
    // TODO: make this do real things

    self.pos += 1;

    match self.pos {
      1 => self.integer(),
      2 => self.plus(),
      3 => self.integer(),
      4 => None,
      _ => {
        println!("----------{:?}", self.pos);
        panic!();
      }
    }
  }
}

struct Parser {
  text: String,
  lexer: Lexer,
  current_token: Option<Token>,
}

impl Parser {
  pub fn new(text: String) -> Parser {
    let mut lexer = Lexer::new(text.clone());

    let token = lexer.get_next_token();

    Parser {
      text: text,
      lexer: lexer,
      current_token: token,
    }
  }

  pub fn eat(&mut self) {
    self.current_token = self.lexer.get_next_token();
  }

  pub fn factor(&mut self) -> Option<Expr> {
    let token = self.current_token.clone();
    self.eat();

    match token {
      Some(Token::Integer(n)) => {
        return Some(Expr::Integer(n));
      }
      Some(t) => {
        println!("--------------------{:?}", t);
        panic!();
      }
      _ => panic!()
    }
  }

  pub fn expr(&mut self) -> Option<Expr> {
    let factor = self.factor();

    let token = self.current_token.clone();
    self.eat();

    match token {
      Some(Token::Plus) => {
        let right = self.current_token.clone();

        match (factor, right) {
          (
            Some(e),
            Some(Token::Integer(n2)),
          ) => Some(
            Expr::BinOp(
              Op::Plus,
              Box::new(e),
              Box::new(Expr::Integer(n2)),
            )
          ),
          (a, b) => {
            println!("token: {:?}", a);
            println!("right: {:?}", b);
            panic!();
          }
        }
      },
      _ => panic!()
    }
  }
}

pub fn parse(input: &str) -> Expr {
  let mut parser = Parser::new(input.to_string());

  match parser.expr() {
    Some(e) => e,
    None => panic!(),
  }
}

#[test]
fn test_parse_int() {

  assert_eq!(
    Expr::BinOp(
      Op::Plus,
        Box::new(Expr::Integer(3)),
        Box::new(Expr::Integer(4)),
      ),
    parse("3+4")
  );
}
<commit_msg>hard-code expr with two pluses<commit_after>use expr::{Expr, Op};

#[derive(Clone, Debug, PartialEq)]
enum Token {
  Plus,
  Integer(i64),
}

struct Lexer {
  text: String,
  pos: i64,
}

impl Lexer {
  pub fn new(text: String) -> Lexer {
    Lexer { text: text, pos: 0 }
  }

  fn remove_first(&mut self, n: usize) {
    let t = self.text.clone();
    let (old, remainder) = t.split_at(n);
    self.text = remainder.to_string();
  }

  pub fn integer(&mut self) -> Option<Token> {
    let int_str: String = self.text
      .chars()
      .take_while(|c| c.is_digit(10))
      .collect();

    match int_str.parse::<i64>() {
      Ok(n) => {
        self.remove_first(int_str.len());
        return Some(Token::Integer(n));
      }
      Err(e) => {
        println!("---------------{:?}", e);
        panic!();
      }
    }

    None
  }

  pub fn plus(&mut self) -> Option<Token> {
    if self.text.starts_with('+') {
      self.remove_first(1);
      return Some(Token::Plus);
    } else {
      panic!();
    }
  }

  pub fn get_next_token(&mut self) -> Option<Token> {
    // TODO: make this do real things

    self.pos += 1;

    match self.pos {
      1 => self.integer(),
      2 => self.plus(),
      3 => self.integer(),
      4 => self.plus(),
      5 => self.integer(),
      6 => None,
      _ => {
        println!("----------{:?}", self.pos);
        panic!();
      }
    }
  }
}

struct Parser {
  text: String,
  lexer: Lexer,
}

impl Parser {
  pub fn new(text: String) -> Parser {
    let mut lexer = Lexer::new(text.clone());

    Parser {
      text: text,
      lexer: lexer,
    }
  }

  pub fn factor(&mut self) -> Option<Expr> {
    let token = self.lexer.get_next_token();

    match token {
      Some(Token::Integer(n)) => {
        return Some(Expr::Integer(n));
      }
      Some(t) => {
        println!("invalid factor: {:?}", t);
        panic!();
      }
      _ => panic!()
    }
  }

  pub fn expr(&mut self) -> Option<Expr> {
    let mut node = self.factor();

    let mut token = self.lexer.get_next_token();

    while token == Some(Token::Plus) {
      match token {
        Some(Token::Plus) => {
          let right = self.factor();

          match (node, right) {
            (Some(e1), Some(e2)) => {
              node = Some(
                Expr::BinOp(
                  Op::Plus,
                  Box::new(e1),
                  Box::new(e2),
                )
              );
            },
            (a, b) => {
              println!("token: {:?}", a);
              println!("right: {:?}", b);
              panic!();
            }
          }
        },
        _ => panic!()
      }

      token = self.lexer.get_next_token();
      println!("------- token: {:?}", token);
    }

    node
  }
}

pub fn parse(input: &str) -> Expr {
  let mut parser = Parser::new(input.to_string());

  match parser.expr() {
    Some(e) => e,
    None => panic!(),
  }
}

#[test]
fn test_parse_int() {

  /*
  assert_eq!(
    Expr::BinOp(
      Op::Plus,
        Box::new(Expr::Integer(3)),
        Box::new(Expr::Integer(4)),
      ),
    parse("3+4")
  );
  */

  assert_eq!(
    Expr::BinOp(
      Op::Plus,
      Box::new(Expr::BinOp(
        Op::Plus,
        Box::new(Expr::Integer(3)),
        Box::new(Expr::Integer(4)),
        ),
      ),
      Box::new(Expr::Integer(5)),
    ),
    parse("3+4+5")
  );
}
<|endoftext|>


<commit_before><commit_msg>OK, undo last commit since rustc is confused about imports in tests?<commit_after><|endoftext|>


<commit_before><commit_msg>Debug-print character in error message.<commit_after><|endoftext|>


<commit_before>use eventual::Async;
use portaudio;
use std::sync::{mpsc, Mutex, Arc, Condvar, MutexGuard};
use std::thread;
use vorbis;

use metadata::Track;
use session::Session;
use audio_decrypt::AudioDecrypt;
use util::{self, SpotifyId, Subfile};
use spirc::{SpircState, SpircDelegate, PlayStatus};

pub struct Player {
    state: Arc<(Mutex<PlayerState>, Condvar)>,

    commands: mpsc::Sender<PlayerCommand>,
}

pub struct PlayerState {
    status: PlayStatus,
    position_ms: u32,
    position_measured_at: i64,
    update_time: i64,

    end_of_track: bool
}

struct PlayerInternal {
    state: Arc<(Mutex<PlayerState>, Condvar)>,
    session: Session,
    commands: mpsc::Receiver<PlayerCommand>,
}

enum PlayerCommand {
    Load(SpotifyId, bool, u32),
    Play,
    Pause,
    Stop,
    Seek(u32)
}

impl Player {
    pub fn new(session: &Session) -> Player {
        let (cmd_tx, cmd_rx) = mpsc::channel();

        let state = Arc::new((Mutex::new(PlayerState {
            status: PlayStatus::kPlayStatusStop,
            position_ms: 0,
            position_measured_at: 0,
            update_time: util::now_ms(),
            end_of_track: false,
        }), Condvar::new()));

        let internal = PlayerInternal {
            session: session.clone(),
            commands: cmd_rx,
            state: state.clone()
        };

        thread::spawn(move || {
            internal.run()
        });

        Player {
            commands: cmd_tx,
            state: state,
        }
    }

    fn command(&self, cmd: PlayerCommand) {
        self.commands.send(cmd).unwrap();
    }
}

impl PlayerInternal {
    fn run(self) {
        portaudio::initialize().unwrap();

        let stream = portaudio::stream::Stream::<i16, i16>::open_default(
                0, 2, 44100.0,
                portaudio::stream::FRAMES_PER_BUFFER_UNSPECIFIED,
                None
        ).unwrap();

        let mut decoder = None;

        loop {
            match self.commands.try_recv() {
                Ok(PlayerCommand::Load(track_id, play, position)) => {
                    self.update(|state| {
                        if state.status == PlayStatus::kPlayStatusPlay {
                            stream.stop().unwrap();
                        }
                        state.end_of_track = false;
                        state.status = PlayStatus::kPlayStatusLoading;
                        state.position_ms = position;
                        state.position_measured_at = util::now_ms();
                        return true;
                    });

                    let track = self.session.metadata::<Track>(track_id).await().unwrap();

                    let file_id = track.files[0];

                    let key = self.session.audio_key(track.id, file_id).await().unwrap();
                    decoder = Some(
                        vorbis::Decoder::new(
                        Subfile::new(
                        AudioDecrypt::new(key,
                        self.session.audio_file(file_id)), 0xa7)).unwrap());
                    decoder.as_mut().unwrap().time_seek(position as f64 / 1000f64).unwrap();

                    self.update(|state| {
                        state.status = if play {
                            stream.start().unwrap();
                            PlayStatus::kPlayStatusPlay
                        } else {
                            PlayStatus::kPlayStatusPause
                        };
                        state.position_ms = position;
                        state.position_measured_at = util::now_ms();

                        return true;
                    });
                    println!("Load Done");
                }
                Ok(PlayerCommand::Seek(ms)) => {
                    decoder.as_mut().unwrap().time_seek(ms as f64 / 1000f64).unwrap();
                    self.update(|state| {
                        state.position_ms = (decoder.as_mut().unwrap().time_tell().unwrap() * 1000f64) as u32;
                        state.position_measured_at = util::now_ms();
                        return true;
                    });
                },
                Ok(PlayerCommand::Play) => {
                    self.update(|state| {
                        state.status = PlayStatus::kPlayStatusPlay;
                        return true;
                    });

                    stream.start().unwrap();
                },
                Ok(PlayerCommand::Pause) => {
                    self.update(|state| {
                        state.status = PlayStatus::kPlayStatusPause;
                        state.update_time = util::now_ms();
                        return true;
                    });

                    stream.stop().unwrap();
                },
                Ok(PlayerCommand::Stop) => {
                    self.update(|state| {
                        if state.status == PlayStatus::kPlayStatusPlay {
                            state.status = PlayStatus::kPlayStatusPause;
                        }
                        return true;
                    });

                    stream.stop().unwrap();
                    decoder = None;
                },
                Err(..) => (),
            }

            if self.state.0.lock().unwrap().status == PlayStatus::kPlayStatusPlay {
                match decoder.as_mut().unwrap().packets().next() {
                    Some(Ok(packet)) => {
                        match stream.write(&packet.data) {
                            Ok(_) => (),
                            Err(portaudio::PaError::OutputUnderflowed)
                                => eprintln!("Underflow"),
                            Err(e) => panic!("PA Error {}", e)
                        };
                    },
                    Some(Err(vorbis::VorbisError::Hole)) => (),
                    Some(Err(e)) => panic!("Vorbis error {:?}", e),
                    None => {
                        self.update(|state| {
                            state.status = PlayStatus::kPlayStatusStop;
                            state.end_of_track = true;
                            return true;
                        });

                        stream.stop().unwrap();
                        decoder = None;
                    }
                }

                self.update(|state| {
                    let now = util::now_ms();

                    if now - state.position_measured_at > 5000 {
                        state.position_ms = (decoder.as_mut().unwrap().time_tell().unwrap() * 1000f64) as u32;
                        state.position_measured_at = now;
                        return true;
                    } else {
                        return false;
                    }
                });
            }
        }

        drop(stream);

        portaudio::terminate().unwrap();
    }

    fn update<F>(&self, f: F)
        where F: FnOnce(&mut MutexGuard<PlayerState>) -> bool {
        let mut guard = self.state.0.lock().unwrap();
        let update = f(&mut guard);
        if update {
            guard.update_time = util::now_ms();
            self.state.1.notify_all();
        }
    }
}

impl SpircDelegate for Player {
    type State = PlayerState;

    fn load(&self, track: SpotifyId,
            start_playing: bool, position_ms: u32) {
        self.command(PlayerCommand::Load(track, start_playing, position_ms));
    }

    fn play(&self) {
        self.command(PlayerCommand::Play)
    }

    fn pause(&self) {
        self.command(PlayerCommand::Pause)
    }

    fn stop(&self) {
        self.command(PlayerCommand::Stop)
    }

    fn seek(&self, position_ms: u32) {
        self.command(PlayerCommand::Seek(position_ms));
    }

    fn state(&self) -> MutexGuard<Self::State> {
        self.state.0.lock().unwrap()
    }

    fn updates(&self) -> mpsc::Receiver<i64> {
        let state = self.state.clone();
        let (update_tx, update_rx) = mpsc::channel();

        thread::spawn(move || {
            let mut guard = state.0.lock().unwrap();
            let mut last_update;
            loop {
                last_update = guard.update_time;
                update_tx.send(guard.update_time).unwrap();

                while last_update >= guard.update_time {
                    guard = state.1.wait(guard).unwrap();
                }
            }
        });

        return update_rx;
    }
}

impl SpircState for PlayerState {
    fn status(&self) -> PlayStatus {
        return self.status;
    }

    fn position(&self) -> (u32, i64) {
        return (self.position_ms, self.position_measured_at);
    }

    fn update_time(&self) -> i64 {
        return self.update_time;
    }

    fn end_of_track(&self) -> bool {
        return self.end_of_track;
    }
}

<commit_msg>Play an alternative track if selected one is not available.<commit_after>use eventual::{self, Async};
use portaudio;
use std::sync::{mpsc, Mutex, Arc, Condvar, MutexGuard};
use std::thread;
use vorbis;

use metadata::{Track, TrackRef};
use session::Session;
use audio_decrypt::AudioDecrypt;
use util::{self, SpotifyId, Subfile};
use spirc::{SpircState, SpircDelegate, PlayStatus};

pub struct Player {
    state: Arc<(Mutex<PlayerState>, Condvar)>,

    commands: mpsc::Sender<PlayerCommand>,
}

pub struct PlayerState {
    status: PlayStatus,
    position_ms: u32,
    position_measured_at: i64,
    update_time: i64,

    end_of_track: bool
}

struct PlayerInternal {
    state: Arc<(Mutex<PlayerState>, Condvar)>,
    session: Session,
    commands: mpsc::Receiver<PlayerCommand>,
}

enum PlayerCommand {
    Load(SpotifyId, bool, u32),
    Play,
    Pause,
    Stop,
    Seek(u32)
}

impl Player {
    pub fn new(session: &Session) -> Player {
        let (cmd_tx, cmd_rx) = mpsc::channel();

        let state = Arc::new((Mutex::new(PlayerState {
            status: PlayStatus::kPlayStatusStop,
            position_ms: 0,
            position_measured_at: 0,
            update_time: util::now_ms(),
            end_of_track: false,
        }), Condvar::new()));

        let internal = PlayerInternal {
            session: session.clone(),
            commands: cmd_rx,
            state: state.clone()
        };

        thread::spawn(move || {
            internal.run()
        });

        Player {
            commands: cmd_tx,
            state: state,
        }
    }

    fn command(&self, cmd: PlayerCommand) {
        self.commands.send(cmd).unwrap();
    }
}

impl PlayerInternal {
    fn run(self) {
        portaudio::initialize().unwrap();

        let stream = portaudio::stream::Stream::<i16, i16>::open_default(
                0, 2, 44100.0,
                portaudio::stream::FRAMES_PER_BUFFER_UNSPECIFIED,
                None
        ).unwrap();

        let mut decoder = None;

        loop {
            match self.commands.try_recv() {
                Ok(PlayerCommand::Load(track_id, play, position)) => {
                    self.update(|state| {
                        if state.status == PlayStatus::kPlayStatusPlay {
                            stream.stop().unwrap();
                        }
                        state.end_of_track = false;
                        state.status = PlayStatus::kPlayStatusLoading;
                        state.position_ms = position;
                        state.position_measured_at = util::now_ms();
                        return true;
                    });
                    drop(decoder);

                    let mut track = self.session.metadata::<Track>(track_id).await().unwrap();

                    if !track.available {
                        let alternatives = track.alternatives.iter()
                            .map(|alt_id| self.session.metadata::<Track>(*alt_id))
                            .collect::<Vec<TrackRef>>();

                        track = eventual::sequence(alternatives.into_iter()).iter().find(|alt| alt.available).unwrap();
                    }

                    let file_id = track.files[0];

                    let key = self.session.audio_key(track.id, file_id).await().unwrap();
                    decoder = Some(
                        vorbis::Decoder::new(
                        Subfile::new(
                        AudioDecrypt::new(key,
                        self.session.audio_file(file_id)), 0xa7)).unwrap());
                    decoder.as_mut().unwrap().time_seek(position as f64 / 1000f64).unwrap();

                    self.update(|state| {
                        state.status = if play {
                            stream.start().unwrap();
                            PlayStatus::kPlayStatusPlay
                        } else {
                            PlayStatus::kPlayStatusPause
                        };
                        state.position_ms = position;
                        state.position_measured_at = util::now_ms();

                        return true;
                    });
                    println!("Load Done");
                }
                Ok(PlayerCommand::Seek(ms)) => {
                    decoder.as_mut().unwrap().time_seek(ms as f64 / 1000f64).unwrap();
                    self.update(|state| {
                        state.position_ms = (decoder.as_mut().unwrap().time_tell().unwrap() * 1000f64) as u32;
                        state.position_measured_at = util::now_ms();
                        return true;
                    });
                },
                Ok(PlayerCommand::Play) => {
                    self.update(|state| {
                        state.status = PlayStatus::kPlayStatusPlay;
                        return true;
                    });

                    stream.start().unwrap();
                },
                Ok(PlayerCommand::Pause) => {
                    self.update(|state| {
                        state.status = PlayStatus::kPlayStatusPause;
                        state.update_time = util::now_ms();
                        return true;
                    });

                    stream.stop().unwrap();
                },
                Ok(PlayerCommand::Stop) => {
                    self.update(|state| {
                        if state.status == PlayStatus::kPlayStatusPlay {
                            state.status = PlayStatus::kPlayStatusPause;
                        }
                        return true;
                    });

                    stream.stop().unwrap();
                    decoder = None;
                },
                Err(..) => (),
            }

            if self.state.0.lock().unwrap().status == PlayStatus::kPlayStatusPlay {
                match decoder.as_mut().unwrap().packets().next() {
                    Some(Ok(packet)) => {
                        match stream.write(&packet.data) {
                            Ok(_) => (),
                            Err(portaudio::PaError::OutputUnderflowed)
                                => eprintln!("Underflow"),
                            Err(e) => panic!("PA Error {}", e)
                        };
                    },
                    Some(Err(vorbis::VorbisError::Hole)) => (),
                    Some(Err(e)) => panic!("Vorbis error {:?}", e),
                    None => {
                        self.update(|state| {
                            state.status = PlayStatus::kPlayStatusStop;
                            state.end_of_track = true;
                            return true;
                        });

                        stream.stop().unwrap();
                        decoder = None;
                    }
                }

                self.update(|state| {
                    let now = util::now_ms();

                    if now - state.position_measured_at > 5000 {
                        state.position_ms = (decoder.as_mut().unwrap().time_tell().unwrap() * 1000f64) as u32;
                        state.position_measured_at = now;
                        return true;
                    } else {
                        return false;
                    }
                });
            }
        }

        drop(stream);

        portaudio::terminate().unwrap();
    }

    fn update<F>(&self, f: F)
        where F: FnOnce(&mut MutexGuard<PlayerState>) -> bool {
        let mut guard = self.state.0.lock().unwrap();
        let update = f(&mut guard);
        if update {
            guard.update_time = util::now_ms();
            self.state.1.notify_all();
        }
    }
}

impl SpircDelegate for Player {
    type State = PlayerState;

    fn load(&self, track: SpotifyId,
            start_playing: bool, position_ms: u32) {
        self.command(PlayerCommand::Load(track, start_playing, position_ms));
    }

    fn play(&self) {
        self.command(PlayerCommand::Play)
    }

    fn pause(&self) {
        self.command(PlayerCommand::Pause)
    }

    fn stop(&self) {
        self.command(PlayerCommand::Stop)
    }

    fn seek(&self, position_ms: u32) {
        self.command(PlayerCommand::Seek(position_ms));
    }

    fn state(&self) -> MutexGuard<Self::State> {
        self.state.0.lock().unwrap()
    }

    fn updates(&self) -> mpsc::Receiver<i64> {
        let state = self.state.clone();
        let (update_tx, update_rx) = mpsc::channel();

        thread::spawn(move || {
            let mut guard = state.0.lock().unwrap();
            let mut last_update;
            loop {
                last_update = guard.update_time;
                update_tx.send(guard.update_time).unwrap();

                while last_update >= guard.update_time {
                    guard = state.1.wait(guard).unwrap();
                }
            }
        });

        return update_rx;
    }
}

impl SpircState for PlayerState {
    fn status(&self) -> PlayStatus {
        return self.status;
    }

    fn position(&self) -> (u32, i64) {
        return (self.position_ms, self.position_measured_at);
    }

    fn update_time(&self) -> i64 {
        return self.update_time;
    }

    fn end_of_track(&self) -> bool {
        return self.end_of_track;
    }
}

<|endoftext|>


<commit_before><commit_msg>It didn't compile in 1.8.0 or 1.9.0.<commit_after><|endoftext|>


<commit_before>extern crate csv;

use super::pokemon_model;
use super::natures;
use super::enums;
use super::stats;
use super::determinant_values;
use super::movedex;
use super::moves;

use std::collections::HashMap;

///Represents a single Token of a Pokemon with individual values for this token.
#[derive(Debug, Clone)]
pub struct PokemonToken {
    pokedex_id: usize,
    name: String,
    level: u16,
    height: u8,
    weight: u16,
    gender: enums::Gender,
    type_one: enums::types,
    type_two: enums::types,
    non_volatile_status: (enums::Non_Volatile, u8),
    move_one: Option<(moves::Technique, u8)>,
    move_two: Option<(moves::Technique, u8)>,
    move_three: Option<(moves::Technique, u8)>,
    move_four: Option<(moves::Technique, u8)>,
    nature: natures::Nature,
    dv: determinant_values::Dv,
    base_stats: stats::Stats,
    current_stats: stats::Stats,
    end_of_turn_flags: HashMap<enums::End_Of_Turn, u8>,
    description: String,
    mega_evolution: Option<pokemon_model::PokemonModel>,
}

impl PokemonToken {
    ///Provides a Pokemon Token from a given model.
    pub fn from_model(model: pokemon_model::PokemonModel) -> PokemonToken {
        let dv = determinant_values::Dv::get_dvs(model.clone());
        let current = stats::Stats::calculate_stats(model.clone(), dv.clone());

        PokemonToken {
            pokedex_id: model.get_id(),
            name: model.get_name(),
            level: 50,
            height: model.get_height(),
            weight: model.get_weight(),
            gender: enums::get_gender(model.clone().get_gender_rate()),
            type_one: model.get_types().0,
            type_two: model.get_types().1,
            non_volatile_status: (enums::Non_Volatile::Undefined, 0),
            move_one: None,
            move_two: None,
            move_three: None,
            move_four: None,
            nature: natures::Nature::get_random_nature(),
            dv: dv,
            base_stats: model.get_stats(),
            current_stats: current,
            end_of_turn_flags: HashMap::new(),
            description: model.get_description(),
            mega_evolution: model.get_mega(),
        }
    }

    pub fn is_asleep(&self) -> bool {
        self.non_volatile_status.0 == enums::Non_Volatile::Sleep
    }

    pub fn get_moves(&self, dex: movedex::Movedex) -> movedex::Movedex {
        dex.for_token(self.get_level(), self.pokedex_id)
    }

    pub fn get_id(&self) -> usize {
        self.pokedex_id
    }

    pub fn get_name(&self) -> String {
        self.clone().name
    }

    pub fn get_level(&self) -> u16 {
        self.clone().level
    }

    pub fn get_gender(&self) -> enums::Gender {
        self.clone().gender
    }

    pub fn get_types(&self) -> (enums::types, enums::types) {
        (self.clone().type_one, self.clone().type_two)
    }

    pub fn get_nature(&self) -> natures::Nature {
        self.clone().nature
    }

    pub fn get_non_volatile(&self) ->(enums::Non_Volatile, u8) {
        self.clone().non_volatile_status
    }

    pub fn get_dv(&self) -> determinant_values::Dv {
        self.clone().dv
    }

    pub fn get_current(&self) -> stats::Stats {
        self.current_stats.clone()
    }

    pub fn get_base(&self) -> stats::Stats {
        self.base_stats.clone()
    }

    pub fn get_end_of_turn_flags(&self) -> HashMap<enums::End_Of_Turn, u8> {
        self.clone().end_of_turn_flags
    }

    pub fn get_mega(&self) -> Option<PokemonToken> {
        if self.mega_evolution.is_some() {
            return Some(PokemonToken::from_model(self.mega_evolution.clone().unwrap()));
        }
        None
    }

// TO-DO: Getter methoden für move bestimmt fehlerbehaftet (unwrap() Aufruf)
    pub fn get_move_one(self) -> Option<moves::Technique> {
        Some(self.move_one.unwrap().0)
    }
    pub fn get_move_two(self) -> Option<moves::Technique> {
        Some(self.move_two.unwrap().0)
    }
    pub fn get_move_three(self) -> Option<moves::Technique> {
        Some(self.move_three.unwrap().0)
    }
    pub fn get_move_four(self) -> Option<moves::Technique> {
        Some(self.move_four.unwrap().0)
    }

    pub fn set_non_volatile(&mut self, status: enums::Non_Volatile) {
        self.non_volatile_status = (status, 0);
    }

    pub fn add_end_flag(&mut self, flag: enums::End_Of_Turn) {
        self.end_of_turn_flags.insert(flag, 0);
    }

    pub fn set_moves(&mut self, moves: Vec<moves::Technique>) {
        self.move_one = Some((moves[0].clone(), moves[0].get_power_points().unwrap()));
        if moves.len() >= 1 {
            self.move_two = Some((moves[1].clone(), moves[1].get_power_points().unwrap()));
        }
        if moves.len() >= 2 {
            self.move_three = Some((moves[2].clone(), moves[2].get_power_points().unwrap()));
        }
        if moves.len() >= 3 {
            self.move_four = Some((moves[3].clone(), moves[3].get_power_points().unwrap()));
        }
    }

    pub fn set_type(&mut self, position: u8, change: enums::types) {
        match position {
            0 => self.type_one = change,
            1 => self.type_two = change,
            _ => unreachable!(),
        }
    }

    pub fn decrement_ap(&mut self) {
        unimplemented!();
    }
}
<commit_msg>completed to_do for pokemon_token.rs/get_move functions<commit_after>extern crate csv;

use super::pokemon_model;
use super::natures;
use super::enums;
use super::stats;
use super::determinant_values;
use super::movedex;
use super::moves;

use std::collections::HashMap;

///Represents a single Token of a Pokemon with individual values for this token.
#[derive(Debug, Clone)]
pub struct PokemonToken {
    pokedex_id: usize,
    name: String,
    level: u16,
    height: u8,
    weight: u16,
    gender: enums::Gender,
    type_one: enums::types,
    type_two: enums::types,
    non_volatile_status: (enums::Non_Volatile, u8),
    move_one: Option<(moves::Technique, u8)>,
    move_two: Option<(moves::Technique, u8)>,
    move_three: Option<(moves::Technique, u8)>,
    move_four: Option<(moves::Technique, u8)>,
    nature: natures::Nature,
    dv: determinant_values::Dv,
    base_stats: stats::Stats,
    current_stats: stats::Stats,
    end_of_turn_flags: HashMap<enums::End_Of_Turn, u8>,
    description: String,
    mega_evolution: Option<pokemon_model::PokemonModel>,
}

impl PokemonToken {
    ///Provides a Pokemon Token from a given model.
    pub fn from_model(model: pokemon_model::PokemonModel) -> PokemonToken {
        let dv = determinant_values::Dv::get_dvs(model.clone());
        let current = stats::Stats::calculate_stats(model.clone(), dv.clone());

        PokemonToken {
            pokedex_id: model.get_id(),
            name: model.get_name(),
            level: 50,
            height: model.get_height(),
            weight: model.get_weight(),
            gender: enums::get_gender(model.clone().get_gender_rate()),
            type_one: model.get_types().0,
            type_two: model.get_types().1,
            non_volatile_status: (enums::Non_Volatile::Undefined, 0),
            move_one: None,
            move_two: None,
            move_three: None,
            move_four: None,
            nature: natures::Nature::get_random_nature(),
            dv: dv,
            base_stats: model.get_stats(),
            current_stats: current,
            end_of_turn_flags: HashMap::new(),
            description: model.get_description(),
            mega_evolution: model.get_mega(),
        }
    }

    pub fn is_asleep(&self) -> bool {
        self.non_volatile_status.0 == enums::Non_Volatile::Sleep
    }

    pub fn get_moves(&self, dex: movedex::Movedex) -> movedex::Movedex {
        dex.for_token(self.get_level(), self.pokedex_id)
    }

    pub fn get_id(&self) -> usize {
        self.pokedex_id
    }

    pub fn get_name(&self) -> String {
        self.clone().name
    }

    pub fn get_level(&self) -> u16 {
        self.clone().level
    }

    pub fn get_gender(&self) -> enums::Gender {
        self.clone().gender
    }

    pub fn get_types(&self) -> (enums::types, enums::types) {
        (self.clone().type_one, self.clone().type_two)
    }

    pub fn get_nature(&self) -> natures::Nature {
        self.clone().nature
    }

    pub fn get_non_volatile(&self) ->(enums::Non_Volatile, u8) {
        self.clone().non_volatile_status
    }

    pub fn get_dv(&self) -> determinant_values::Dv {
        self.clone().dv
    }

    pub fn get_current(&self) -> stats::Stats {
        self.current_stats.clone()
    }

    pub fn get_base(&self) -> stats::Stats {
        self.base_stats.clone()
    }

    pub fn get_end_of_turn_flags(&self) -> HashMap<enums::End_Of_Turn, u8> {
        self.clone().end_of_turn_flags
    }

    pub fn get_mega(&self) -> Option<PokemonToken> {
        if self.mega_evolution.is_some() {
            return Some(PokemonToken::from_model(self.mega_evolution.clone().unwrap()));
        }
        None
    }

    /// Getter function for move one. If the move is set, the function returns it, if not,
    /// it returns None
    pub fn get_move_one(self) -> Option<moves::Technique> {
        Some(self.move_one.unwrap_or(return None).0)
    }
    /// Getter function for move two. If the move is set, the function returns it, if not,
    /// it returns None
    pub fn get_move_two(self) -> Option<moves::Technique> {
        Some(self.move_two.unwrap_or(return None).0)
    }
    /// Getter function for move three. If the move is set, the function returns it, if not,
    /// it returns None
    pub fn get_move_three(self) -> Option<moves::Technique> {
        Some(self.move_three.unwrap_or(return None).0)
    }
    /// Getter function for move four. If the move is set, the function returns it, if not,
    /// it returns None
    pub fn get_move_four(self) -> Option<moves::Technique> {
        Some(self.move_four.unwrap_or(return None).0)
    }

    pub fn set_non_volatile(&mut self, status: enums::Non_Volatile) {
        self.non_volatile_status = (status, 0);
    }

    pub fn add_end_flag(&mut self, flag: enums::End_Of_Turn) {
        self.end_of_turn_flags.insert(flag, 0);
    }

    pub fn set_moves(&mut self, moves: Vec<moves::Technique>) {
        self.move_one = Some((moves[0].clone(), moves[0].get_power_points().unwrap()));
        if moves.len() >= 1 {
            self.move_two = Some((moves[1].clone(), moves[1].get_power_points().unwrap()));
        }
        if moves.len() >= 2 {
            self.move_three = Some((moves[2].clone(), moves[2].get_power_points().unwrap()));
        }
        if moves.len() >= 3 {
            self.move_four = Some((moves[3].clone(), moves[3].get_power_points().unwrap()));
        }
    }

    pub fn set_type(&mut self, position: u8, change: enums::types) {
        match position {
            0 => self.type_one = change,
            1 => self.type_two = change,
            _ => unreachable!(),
        }
    }

    pub fn decrement_ap(&mut self) {
        unimplemented!();
    }
}
<|endoftext|>


<commit_before>use database::models::{ToU64, Reaction as DbReaction};

use diesel::prelude::*;

use serenity::client::{Context, EventHandler};
use serenity::model::channel::{Channel, Reaction};

use error::*;

pub struct ReactionAuthorize;

impl EventHandler for ReactionAuthorize {
  fn reaction_add(&self, context: Context, reaction: Reaction) {
    ReactionAuthorize::receive(context, &reaction, true);
  }

  fn reaction_remove(&self, context: Context, reaction: Reaction) {
    ReactionAuthorize::receive(context, &reaction, false);
  }
}

impl ReactionAuthorize {
  fn receive(_: Context, r: &Reaction, added: bool) {
    let inner = || -> Result<()> {
      let channel = match r.channel_id.get().chain_err(|| "could not get channel")? {
        Channel::Guild(c) => c.read().clone(),
        _ => bail!("invalid channel: {}", r.channel_id.0)
      };
      let emoji = r.emoji.to_string();
      let reactions: Vec<DbReaction> = ::bot::CONNECTION.with(|c| {
        use database::schema::reactions::dsl;
        dsl::reactions
          .filter(dsl::channel_id.eq(r.channel_id.to_u64())
            .and(dsl::server_id.eq(channel.guild_id.to_u64()))
            .and(dsl::message_id.eq(r.message_id.to_u64()))
            .and(dsl::emoji.eq(emoji)))
          .load(c)
          .chain_err(|| "could not load reactions")
      })?;
      let guild = channel.guild_id.get().chain_err(|| "could not get guild")?;
      let mut member = guild.member(r.user_id).chain_err(|| "could not get member")?;
      for reac in reactions {
        if added {
          member.add_role(*reac.role_id).chain_err(|| "could not add role")?;
        } else {
          member.remove_role(*reac.role_id).chain_err(|| "could not remove role")?;
        }
      }
      Ok(())
    };
    if let Err(e) = inner() {
      warn!("ReactionAuthorize error: {}", e);
    }
  }
}
<commit_msg>refactor: silently ignore instead of fail on invalid channel<commit_after>use database::models::{ToU64, Reaction as DbReaction};

use diesel::prelude::*;

use serenity::client::{Context, EventHandler};
use serenity::model::channel::{Channel, Reaction};

use error::*;

pub struct ReactionAuthorize;

impl EventHandler for ReactionAuthorize {
  fn reaction_add(&self, context: Context, reaction: Reaction) {
    ReactionAuthorize::receive(context, &reaction, true);
  }

  fn reaction_remove(&self, context: Context, reaction: Reaction) {
    ReactionAuthorize::receive(context, &reaction, false);
  }
}

impl ReactionAuthorize {
  fn receive(_: Context, r: &Reaction, added: bool) {
    let inner = || -> Result<()> {
      let channel = match r.channel_id.get().chain_err(|| "could not get channel")? {
        Channel::Guild(c) => c.read().clone(),
        _ => return Ok(())
      };
      let emoji = r.emoji.to_string();
      let reactions: Vec<DbReaction> = ::bot::CONNECTION.with(|c| {
        use database::schema::reactions::dsl;
        dsl::reactions
          .filter(dsl::channel_id.eq(r.channel_id.to_u64())
            .and(dsl::server_id.eq(channel.guild_id.to_u64()))
            .and(dsl::message_id.eq(r.message_id.to_u64()))
            .and(dsl::emoji.eq(emoji)))
          .load(c)
          .chain_err(|| "could not load reactions")
      })?;
      let guild = channel.guild_id.get().chain_err(|| "could not get guild")?;
      let mut member = guild.member(r.user_id).chain_err(|| "could not get member")?;
      for reac in reactions {
        if added {
          member.add_role(*reac.role_id).chain_err(|| "could not add role")?;
        } else {
          member.remove_role(*reac.role_id).chain_err(|| "could not remove role")?;
        }
      }
      Ok(())
    };
    if let Err(e) = inner() {
      warn!("ReactionAuthorize error: {}", e);
    }
  }
}
<|endoftext|>


<commit_before>use log_parser::*;
use timing_analyzer::Timing;
use error_analyzer::HttpErrorState;

#[derive(Clone, Debug)]
pub struct RequestResponsePair {
    pub request: log_events::Request,
    pub response: log_events::Response,
}

pub fn extract_matching_request_response_pairs(requests: &mut Vec<log_events::Request>,
                                               responses: &mut Vec<log_events::Response>)
                                               -> Vec<RequestResponsePair> {
    let mut request_response_pairs: Vec<RequestResponsePair> = Vec::new();

    for request_index in 0..requests.len() {
        {
            let request = requests.get(request_index);

            if request.is_none() {
                continue;
            }
        }

        let matching_response_index: Option<usize> = responses.iter()
            .position(|response| requests[request_index].id == response.id);

        if matching_response_index.is_some() {
            let request = requests.remove(request_index);
            let response = responses.remove(matching_response_index.unwrap());

            let pair = RequestResponsePair {
                request: request,
                response: response,
            };

            request_response_pairs.push(pair);
        }
    }

    request_response_pairs
}

impl Timing for RequestResponsePair {
    fn num_milliseconds(&self) -> i64 {
        self.response.response_time.num_milliseconds()
    }
}

impl Timing for Box<Timing> {
    fn num_milliseconds(&self) -> i64 {
        (**self).num_milliseconds()
    }
}

impl Timing for Box<RequestResponsePair> {
    fn num_milliseconds(&self) -> i64 {
        (**self).num_milliseconds()
    }
}

impl HttpErrorState for RequestResponsePair {
    fn error(&self) -> Option<log_events::HttpError> {
        self.response.http_error.clone()
    }
}

impl HttpErrorState for Box<RequestResponsePair> {
    fn error(&self) -> Option<log_events::HttpError> {
        (**self).error()
    }
}

#[cfg(test)]
mod tests {
    use chrono::*;
    use super::*;
    use log_parser;
    use timing_analyzer::Timing;
    use error_analyzer::HttpErrorState;

    #[test]
    fn test_extract_matching_request_response_pairs() {
        let mut requests = vec![log_parser::log_events::Request {
                                    id: 1,
                                    time: DateTime::parse_from_str("08/Apr/2016:09:57:47 +0200",
                                                                   "%d/%b/%Y:%H:%M:%S %z")
                                        .unwrap(),
                                    original_log_line: "whatever".to_string(),
                                },
                                log_parser::log_events::Request {
                                    id: 77,
                                    time: DateTime::parse_from_str("08/Apr/2016:09:57:47 +0200",
                                                                   "%d/%b/%Y:%H:%M:%S %z")
                                        .unwrap(),
                                    original_log_line: "whatever".to_string(),
                                }];

        let mut responses = vec![log_parser::log_events::Response {
                                     id: 1,
                                     response_time: Duration::milliseconds(7),
                                     original_log_line: "whatever".to_string(),
                                     http_error: None,
                                 },
                                 log_parser::log_events::Response {
                                     id: 99,
                                     response_time: Duration::milliseconds(10),
                                     original_log_line: "whatever".to_string(),
                                     http_error: None,
                                 }];

        let result = extract_matching_request_response_pairs(&mut requests, &mut responses);

        assert_eq!(result.len(), 1);
        assert_eq!(result[0].request.id, 1);
        assert_eq!(result[0].response.id, 1);

        assert_eq!(requests.len(), 1);
        assert_eq!(responses.len(), 1);
    }

    #[test]
    fn test_timing_trait() {
        let timing: &Timing = &RequestResponsePair {
            request: log_parser::log_events::Request {
                id: 1,
                time: DateTime::parse_from_str("08/Apr/2016:09:57:47 +0200",
                                               "%d/%b/%Y:%H:%M:%S %z")
                    .unwrap(),
                original_log_line: "whatever".to_string(),
            },
            response: log_parser::log_events::Response {
                id: 1,
                response_time: Duration::milliseconds(7),
                original_log_line: "whatever".to_string(),
                http_error: None,
            },
        } as &Timing;

        let result: i64 = timing.num_milliseconds();
        assert_eq!(result, 7);

        let boxed_timing = Box::new(timing);

        let result: i64 = boxed_timing.num_milliseconds();
        assert_eq!(result, 7);
    }

    #[test]
    fn test_http_error_state_trait() {
        let state: &HttpErrorState = &RequestResponsePair {
            request: log_parser::log_events::Request {
                id: 1,
                time: DateTime::parse_from_str("08/Apr/2016:09:57:47 +0200",
                                               "%d/%b/%Y:%H:%M:%S %z")
                    .unwrap(),
                original_log_line: "whatever".to_string(),
            },
            response: log_parser::log_events::Response {
                id: 1,
                response_time: Duration::milliseconds(7),
                original_log_line: "whatever".to_string(),
                http_error: None,
            },
        } as &HttpErrorState;

        let result = state.error();
        assert_eq!(result, None);

        let boxed_state = Box::new(state);

        let result = boxed_state.error();
        assert_eq!(result, None);
    }
}
<commit_msg>Iterator example that compiles at least<commit_after>use log_parser::*;
use timing_analyzer::Timing;
use error_analyzer::HttpErrorState;
use chrono::*;

#[derive(Clone, Debug, PartialEq)]
pub struct RequestResponsePair {
    pub request: log_events::Request,
    pub response: log_events::Response,
}

pub fn extract_matching_request_response_pairs(requests: &mut Vec<log_events::Request>,
                                               responses: &mut Vec<log_events::Response>)
                                               -> Vec<RequestResponsePair> {
    let mut request_response_pairs: Vec<RequestResponsePair> = Vec::new();

    for request_index in 0..requests.len() {
        {
            let request = requests.get(request_index);

            if request.is_none() {
                continue;
            }
        }

        let matching_response_index: Option<usize> = responses.iter()
            .position(|response| requests[request_index].id == response.id);

        if matching_response_index.is_some() {
            let request = requests.remove(request_index);
            let response = responses.remove(matching_response_index.unwrap());

            let pair = RequestResponsePair {
                request: request,
                response: response,
            };

            request_response_pairs.push(pair);
        }
    }

    request_response_pairs
}

impl Timing for RequestResponsePair {
    fn num_milliseconds(&self) -> i64 {
        self.response.response_time.num_milliseconds()
    }
}

impl Timing for Box<Timing> {
    fn num_milliseconds(&self) -> i64 {
        (**self).num_milliseconds()
    }
}

impl Timing for Box<RequestResponsePair> {
    fn num_milliseconds(&self) -> i64 {
        (**self).num_milliseconds()
    }
}

impl HttpErrorState for RequestResponsePair {
    fn error(&self) -> Option<log_events::HttpError> {
        self.response.http_error.clone()
    }
}

impl HttpErrorState for Box<RequestResponsePair> {
    fn error(&self) -> Option<log_events::HttpError> {
        (**self).error()
    }
}

pub struct RequestResponsePairIterator<'a> {
    // events: Iterator<Item = log_events::LogEvent>,
    // pairs: Vec<RequestResponsePair>,
    pairs: &'a mut Iterator<Item = RequestResponsePair>,
}

impl<'a> Iterator for RequestResponsePairIterator<'a> {
    type Item = RequestResponsePair;
    fn next(&mut self) -> Option<RequestResponsePair> {
        self.pairs.next()
    }
}

// fn extract_matching_request_response_pairs_iter<T, U>(events: T) -> U
//     where T: Iterator<Item = log_events::LogEvent>,
//           U: Iterator<Item = RequestResponsePair>
// {
//     vec![RequestResponsePair {
//              request: log_events::Request {
//                  id: 1,
//                  time: DateTime::parse_from_str("08/Apr/2016:09:57:47 +0200",
//                                                 "%d/%b/%Y:%H:%M:%S %z")
//                      .unwrap(),
//                  original_log_line: "whatever".to_string(),
//              },
//              response: log_events::Response {
//                  id: 1,
//                  response_time: Duration::milliseconds(7),
//                  original_log_line: "whatever".to_string(),
//                  http_error: None,
//              },
//          }]
//         .iter() as U
// }

#[cfg(test)]
mod tests {
    use chrono::*;
    use super::*;
    use log_parser;
    use timing_analyzer::Timing;
    use error_analyzer::HttpErrorState;

    #[test]
    fn test_extract_matching_request_response_pairs() {
        let mut requests = vec![log_parser::log_events::Request {
                                    id: 1,
                                    time: DateTime::parse_from_str("08/Apr/2016:09:57:47 +0200",
                                                                   "%d/%b/%Y:%H:%M:%S %z")
                                        .unwrap(),
                                    original_log_line: "whatever".to_string(),
                                },
                                log_parser::log_events::Request {
                                    id: 77,
                                    time: DateTime::parse_from_str("08/Apr/2016:09:57:47 +0200",
                                                                   "%d/%b/%Y:%H:%M:%S %z")
                                        .unwrap(),
                                    original_log_line: "whatever".to_string(),
                                }];

        let mut responses = vec![log_parser::log_events::Response {
                                     id: 1,
                                     response_time: Duration::milliseconds(7),
                                     original_log_line: "whatever".to_string(),
                                     http_error: None,
                                 },
                                 log_parser::log_events::Response {
                                     id: 99,
                                     response_time: Duration::milliseconds(10),
                                     original_log_line: "whatever".to_string(),
                                     http_error: None,
                                 }];

        let result = extract_matching_request_response_pairs(&mut requests, &mut responses);

        assert_eq!(result.len(), 1);
        assert_eq!(result[0].request.id, 1);
        assert_eq!(result[0].response.id, 1);

        assert_eq!(requests.len(), 1);
        assert_eq!(responses.len(), 1);
    }

    #[test]
    fn test_extract_matching_request_response_pairs_iterator() {
        // let events =
        //     vec![log_parser::log_events::LogEvent::Request(log_parser::log_events::Request {
        //              id: 1,
        //              time: DateTime::parse_from_str("08/Apr/2016:09:57:47 +0200",
        //                                             "%d/%b/%Y:%H:%M:%S %z")
        //                  .unwrap(),
        //              original_log_line: "whatever".to_string(),
        //          }),
        //          log_parser::log_events::LogEvent::Response(log_parser::log_events::Response {
        //              id: 1,
        //              response_time: Duration::milliseconds(7),
        //              original_log_line: "whatever".to_string(),
        //              http_error: None,
        //          })];
        //
        //
        // // let result = extract_matching_request_response_pairs(&mut requests, &mut responses);
        // let result = extract_matching_request_response_pairs_iter(events.iter()).collect();
        //
        // assert_eq!(result.len(), 1);
        // assert_eq!(result[0].request.id, 1);
        // assert_eq!(result[0].response.id, 1);

        let mut iterator = RequestResponsePairIterator {
            pairs: &mut vec![RequestResponsePair {
                                 request: log_events::Request {
                                     id: 1,
                                     time: DateTime::parse_from_str("08/Apr/2016:09:57:47 +0200",
                                                                    "%d/%b/%Y:%H:%M:%S %z")
                                         .unwrap(),
                                     original_log_line: "whatever".to_string(),
                                 },
                                 response: log_events::Response {
                                     id: 1,
                                     response_time: Duration::milliseconds(7),
                                     original_log_line: "whatever".to_string(),
                                     http_error: None,
                                 },
                             }]
                .into_iter() as &mut Iterator<Item = RequestResponsePair>,
        };

        assert_eq!(iterator.next(), None);
    }

    #[test]
    fn test_timing_trait() {
        let timing: &Timing = &RequestResponsePair {
            request: log_parser::log_events::Request {
                id: 1,
                time: DateTime::parse_from_str("08/Apr/2016:09:57:47 +0200",
                                               "%d/%b/%Y:%H:%M:%S %z")
                    .unwrap(),
                original_log_line: "whatever".to_string(),
            },
            response: log_parser::log_events::Response {
                id: 1,
                response_time: Duration::milliseconds(7),
                original_log_line: "whatever".to_string(),
                http_error: None,
            },
        } as &Timing;

        let result: i64 = timing.num_milliseconds();
        assert_eq!(result, 7);

        let boxed_timing = Box::new(timing);

        let result: i64 = boxed_timing.num_milliseconds();
        assert_eq!(result, 7);
    }

    #[test]
    fn test_http_error_state_trait() {
        let state: &HttpErrorState = &RequestResponsePair {
            request: log_parser::log_events::Request {
                id: 1,
                time: DateTime::parse_from_str("08/Apr/2016:09:57:47 +0200",
                                               "%d/%b/%Y:%H:%M:%S %z")
                    .unwrap(),
                original_log_line: "whatever".to_string(),
            },
            response: log_parser::log_events::Response {
                id: 1,
                response_time: Duration::milliseconds(7),
                original_log_line: "whatever".to_string(),
                http_error: None,
            },
        } as &HttpErrorState;

        let result = state.error();
        assert_eq!(result, None);

        let boxed_state = Box::new(state);

        let result = boxed_state.error();
        assert_eq!(result, None);
    }
}
<|endoftext|>