<commit_before>// Copyright 2016 rust-tfidf Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use std::borrow::Borrow;
use num::traits::Float;

use prelude::{ProcessedDocument, NaiveDocument, Tf, NormalizationFactor};

/// Binary weighting scheme for TF. If the document contains the term, returns 1,
/// otherwise returns 0.
#[derive(Copy, Clone)]
pub struct BinaryTf;

impl<T> Tf<T> for BinaryTf where T: NaiveDocument
{
  #[inline]
  fn tf<K>(term: K, doc: &T) -> f64
    where K: Borrow<T::Term>
  {
    if doc.term_exists(term) {
      1f64
    } else {
      0f64
    }
  }
}

/// Raw frequency weighting scheme for TF. Returns the number of times a term occurs
/// in the document.
#[derive(Copy, Clone)]
pub struct RawFrequencyTf(f64);

impl<T> Tf<T> for RawFrequencyTf where T: ProcessedDocument
{
  #[inline]
  fn tf<K>(term: K, doc: &T) -> f64
    where K: Borrow<T::Term>
  {
    doc.term_frequency(term) as f64
  }
}

/// Log normalized weighting scheme for TF. Computes `1 + log (f)` where `f` is the
/// frequency of the term in the document.
#[derive(Copy, Clone)]
pub struct LogNormalizationTf;

impl<T> Tf<T> for LogNormalizationTf where T: ProcessedDocument
{
  #[inline]
  fn tf<K>(term: K, doc: &T) -> f64
    where K: Borrow<T::Term>
  {
    1f64 + (doc.term_frequency(term) as f64).ln()
  }
}

/// Double normalized weighting scheme for TF based on a factor, `K`.
///
/// # Example
///
/// To implement a custom Tf strategy, where the `K` factor is constant:
///
/// ```rust
/// use tfidf::{Tf, NormalizationFactor};
/// use tfidf::tf::{DoubleKNormalizationTf};
///
/// struct DoubleThirdNormalizationTf;
///
/// impl NormalizationFactor for DoubleThirdNormalizationTf {
///   fn factor() -> f64 { 0.3f64 }
/// }
///
/// impl DoubleKNormalizationTf for DoubleThirdNormalizationTf { }
/// ```
pub trait DoubleKNormalizationTf : NormalizationFactor { }

impl<T, S> Tf<T> for S
  where S: DoubleKNormalizationTf,
        T: ProcessedDocument
{
  #[inline]
  fn tf<K>(term: K, doc: &T) -> f64
    where K: Borrow<T::Term>
  {
    let max = match doc.max() {
      Some(m) => doc.term_frequency(m) as f64,
      None => 1f64,
    };

    // K + ((1 - K) * (f / max f))
    S::factor() + ((1f64 - S::factor()) * ((doc.term_frequency(term) as f64) / max))
  }
}

/// Double normalized weighting scheme for TF based on a factor, `K = 0.5`.
#[derive(Copy, Clone)]
pub struct DoubleHalfNormalizationTf;

impl NormalizationFactor for DoubleHalfNormalizationTf {
  #[inline]
  fn factor() -> f64 {
    0.5f64
  }
}

impl DoubleKNormalizationTf for DoubleHalfNormalizationTf {}
<commit_msg>remove unused import<commit_after>// Copyright 2016 rust-tfidf Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use std::borrow::Borrow;

use prelude::{ProcessedDocument, NaiveDocument, Tf, NormalizationFactor};

/// Binary weighting scheme for TF. If the document contains the term, returns 1,
/// otherwise returns 0.
#[derive(Copy, Clone)]
pub struct BinaryTf;

impl<T> Tf<T> for BinaryTf where T: NaiveDocument
{
  #[inline]
  fn tf<K>(term: K, doc: &T) -> f64
    where K: Borrow<T::Term>
  {
    if doc.term_exists(term) {
      1f64
    } else {
      0f64
    }
  }
}

/// Raw frequency weighting scheme for TF. Returns the number of times a term occurs
/// in the document.
#[derive(Copy, Clone)]
pub struct RawFrequencyTf(f64);

impl<T> Tf<T> for RawFrequencyTf where T: ProcessedDocument
{
  #[inline]
  fn tf<K>(term: K, doc: &T) -> f64
    where K: Borrow<T::Term>
  {
    doc.term_frequency(term) as f64
  }
}

/// Log normalized weighting scheme for TF. Computes `1 + log (f)` where `f` is the
/// frequency of the term in the document.
#[derive(Copy, Clone)]
pub struct LogNormalizationTf;

impl<T> Tf<T> for LogNormalizationTf where T: ProcessedDocument
{
  #[inline]
  fn tf<K>(term: K, doc: &T) -> f64
    where K: Borrow<T::Term>
  {
    1f64 + (doc.term_frequency(term) as f64).ln()
  }
}

/// Double normalized weighting scheme for TF based on a factor, `K`.
///
/// # Example
///
/// To implement a custom Tf strategy, where the `K` factor is constant:
///
/// ```rust
/// use tfidf::{Tf, NormalizationFactor};
/// use tfidf::tf::{DoubleKNormalizationTf};
///
/// struct DoubleThirdNormalizationTf;
///
/// impl NormalizationFactor for DoubleThirdNormalizationTf {
///   fn factor() -> f64 { 0.3f64 }
/// }
///
/// impl DoubleKNormalizationTf for DoubleThirdNormalizationTf { }
/// ```
pub trait DoubleKNormalizationTf : NormalizationFactor { }

impl<T, S> Tf<T> for S
  where S: DoubleKNormalizationTf,
        T: ProcessedDocument
{
  #[inline]
  fn tf<K>(term: K, doc: &T) -> f64
    where K: Borrow<T::Term>
  {
    let max = match doc.max() {
      Some(m) => doc.term_frequency(m) as f64,
      None => 1f64,
    };

    // K + ((1 - K) * (f / max f))
    S::factor() + ((1f64 - S::factor()) * ((doc.term_frequency(term) as f64) / max))
  }
}

/// Double normalized weighting scheme for TF based on a factor, `K = 0.5`.
#[derive(Copy, Clone)]
pub struct DoubleHalfNormalizationTf;

impl NormalizationFactor for DoubleHalfNormalizationTf {
  #[inline]
  fn factor() -> f64 {
    0.5f64
  }
}

impl DoubleKNormalizationTf for DoubleHalfNormalizationTf {}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate time;
extern crate curl;
extern crate rustc_serialize;
extern crate openssl;

use std::io::prelude::*;

use curl::easy::{Easy, Transfer, List, ReadError};
use openssl::hash::MessageDigest;
use openssl::sign::Signer;
use openssl::pkey::PKey;
use rustc_serialize::base64::{ToBase64, STANDARD};

pub struct Bucket {
    name: String,
    region: Option<String>,
    access_key: String,
    secret_key: String,
    proto: String,
}

impl Bucket {
    pub fn new(name: String,
               region: Option<String>,
               access_key: String,
               secret_key: String,
               proto: &str) -> Bucket {
        Bucket {
            name: name,
            region: region,
            access_key: access_key,
            secret_key: secret_key,
            proto: proto.to_string(),
        }
    }

    pub fn put<'a, 'b>(&self,
                       easy: &'a mut Easy,
                       path: &str,
                       content: &'b mut Read,
                       content_type: &str,
                       content_length: u64)
                       -> Transfer<'a, 'b> {
        let path = if path.starts_with("/") {&path[1..]} else {path};
        let host = self.host();
        let date = time::now().rfc822z().to_string();
        let auth = self.auth("PUT", &date, path, "", content_type);
        let url = format!("{}://{}/{}", self.proto, host, path);

        let mut headers = List::new();
        headers.append(&format!("Host: {}", host)).unwrap();
        headers.append(&format!("Date: {}", date)).unwrap();
        headers.append(&format!("Authorization: {}", auth)).unwrap();
        headers.append(&format!("Content-Type: {}", content_type)).unwrap();

        // Disable the `Expect: 100-continue` header for now, this cause
        // problems with the test harness currently and the purpose is
        // not yet clear. Would probably be good to reenable at some point.
        headers.append("Expect:").unwrap();

        easy.url(&url).unwrap();
        easy.put(true).unwrap();
        easy.http_headers(headers).unwrap();
        easy.upload(true).unwrap();
        easy.in_filesize(content_length).unwrap();

        let mut transfer = easy.transfer();
        transfer.read_function(move |data| {
            content.read(data).map_err(|_| ReadError::Abort)
        }).unwrap();

        return transfer
    }

    pub fn delete<'a, 'b>(&self,
                          easy: &'a mut Easy,
                          path: &str)
                          -> Transfer<'a, 'b> {
        let path = if path.starts_with("/") {&path[1..]} else {path};
        let host = self.host();
        let date = time::now().rfc822z().to_string();
        let auth = self.auth("DELETE", &date, path, "", "");
        let url = format!("{}://{}/{}", self.proto, host, path);

        let mut headers = List::new();
        headers.append(&format!("Host: {}", host)).unwrap();
        headers.append(&format!("Date: {}", date)).unwrap();
        headers.append(&format!("Authorization: {}", auth)).unwrap();

        easy.custom_request("DELETE").unwrap();
        easy.url(&url).unwrap();
        easy.http_headers(headers).unwrap();

        return easy.transfer()
    }

    pub fn host(&self) -> String {
        format!("{}.s3{}.amazonaws.com", self.name,
                match self.region {
                    Some(ref r) => format!("-{}", r),
                    None => String::new(),
                })
    }

    fn auth(&self, verb: &str, date: &str, path: &str,
            md5: &str, content_type: &str) -> String {
        let string = format!("{verb}\n{md5}\n{ty}\n{date}\n{headers}{resource}",
                             verb = verb,
                             md5 = md5,
                             ty = content_type,
                             date = date,
                             headers = "",
                             resource = format!("/{}/{}", self.name, path));
        let signature = {
            let key = PKey::hmac(self.secret_key.as_bytes()).unwrap();
            let mut signer = Signer::new(MessageDigest::sha1(), &key).unwrap();
            signer.update(string.as_bytes()).unwrap();
            signer.finish().unwrap().to_base64(STANDARD)
        };
        format!("AWS {}:{}", self.access_key, signature)
    }
}
<commit_msg>fix: incorrect host when running tests<commit_after>#![deny(warnings)]

extern crate time;
extern crate curl;
extern crate rustc_serialize;
extern crate openssl;

use std::io::prelude::*;

use curl::easy::{Easy, Transfer, List, ReadError};
use openssl::hash::MessageDigest;
use openssl::sign::Signer;
use openssl::pkey::PKey;
use rustc_serialize::base64::{ToBase64, STANDARD};

pub struct Bucket {
    name: String,
    region: Option<String>,
    access_key: String,
    secret_key: String,
    proto: String,
}

impl Bucket {
    pub fn new(name: String,
               region: Option<String>,
               access_key: String,
               secret_key: String,
               proto: &str) -> Bucket {
        Bucket {
            name: name,
            region: region,
            access_key: access_key,
            secret_key: secret_key,
            proto: proto.to_string(),
        }
    }

    pub fn put<'a, 'b>(&self,
                       easy: &'a mut Easy,
                       path: &str,
                       content: &'b mut Read,
                       content_type: &str,
                       content_length: u64)
                       -> Transfer<'a, 'b> {
        let path = if path.starts_with("/") {&path[1..]} else {path};
        let host = self.host();
        let date = time::now().rfc822z().to_string();
        let auth = self.auth("PUT", &date, path, "", content_type);
        let url = format!("{}://{}/{}", self.proto, host, path);

        let mut headers = List::new();
        headers.append(&format!("Host: {}", host)).unwrap();
        headers.append(&format!("Date: {}", date)).unwrap();
        headers.append(&format!("Authorization: {}", auth)).unwrap();
        headers.append(&format!("Content-Type: {}", content_type)).unwrap();

        // Disable the `Expect: 100-continue` header for now, this cause
        // problems with the test harness currently and the purpose is
        // not yet clear. Would probably be good to reenable at some point.
        headers.append("Expect:").unwrap();

        easy.url(&url).unwrap();
        easy.put(true).unwrap();
        easy.http_headers(headers).unwrap();
        easy.upload(true).unwrap();
        easy.in_filesize(content_length).unwrap();

        let mut transfer = easy.transfer();
        transfer.read_function(move |data| {
            content.read(data).map_err(|_| ReadError::Abort)
        }).unwrap();

        return transfer
    }

    pub fn delete<'a, 'b>(&self,
                          easy: &'a mut Easy,
                          path: &str)
                          -> Transfer<'a, 'b> {
        let path = if path.starts_with("/") {&path[1..]} else {path};
        let host = self.host();
        let date = time::now().rfc822z().to_string();
        let auth = self.auth("DELETE", &date, path, "", "");
        let url = format!("{}://{}/{}", self.proto, host, path);

        let mut headers = List::new();
        headers.append(&format!("Host: {}", host)).unwrap();
        headers.append(&format!("Date: {}", date)).unwrap();
        headers.append(&format!("Authorization: {}", auth)).unwrap();

        easy.custom_request("DELETE").unwrap();
        easy.url(&url).unwrap();
        easy.http_headers(headers).unwrap();

        return easy.transfer()
    }

    pub fn host(&self) -> String {
        format!("{}.s3{}.amazonaws.com", self.name,
                match self.region {
                    Some(ref r) if r != "" => format!("-{}", r),
                    Some(_) => String::new(),
                    None => String::new(),
                })
    }

    fn auth(&self, verb: &str, date: &str, path: &str,
            md5: &str, content_type: &str) -> String {
        let string = format!("{verb}\n{md5}\n{ty}\n{date}\n{headers}{resource}",
                             verb = verb,
                             md5 = md5,
                             ty = content_type,
                             date = date,
                             headers = "",
                             resource = format!("/{}/{}", self.name, path));
        let signature = {
            let key = PKey::hmac(self.secret_key.as_bytes()).unwrap();
            let mut signer = Signer::new(MessageDigest::sha1(), &key).unwrap();
            signer.update(string.as_bytes()).unwrap();
            signer.finish().unwrap().to_base64(STANDARD)
        };
        format!("AWS {}:{}", self.access_key, signature)
    }
}
<|endoftext|>


<commit_before>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use std::mem::transmute;
extern crate itertools;
use self::itertools::Itertools;
extern crate crossbeam;
use std::f32;
use std::cmp;

#[derive(Debug, Clone)]
pub struct ArwDecoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> ArwDecoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> ArwDecoder<'a> {
    ArwDecoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for ArwDecoder<'a> {
  fn identify(&self) -> Result<&Camera, String> {
    let make = fetch_tag!(self.tiff, Tag::Make, "ARW: Couldn't find Make").get_str();
    let model = fetch_tag!(self.tiff, Tag::Model, "ARW: Couldn't find Model").get_str();
    self.rawloader.check_supported(make, model)
  }

  fn image(&self) -> Result<Image,String> {
    let camera = try!(self.identify());
    let data = self.tiff.find_ifds_with_tag(Tag::StripOffsets);
    if data.len() == 0 {
      return Err("ARW: Couldn't find the data IFD!".to_string())
    }
    let raw = data[0];
    let width = fetch_tag!(raw, Tag::ImageWidth, "ARW: Couldn't find width").get_u16(0) as u32;
    let height = fetch_tag!(raw, Tag::ImageLength, "ARW: Couldn't find height").get_u16(0) as u32;
    let offset = fetch_tag!(raw, Tag::StripOffsets, "ARW: Couldn't find offset").get_u32(0) as usize;
    let count = fetch_tag!(raw, Tag::StripByteCounts, "ARW: Couldn't find byte count").get_u32(0) as usize;
    let compression = fetch_tag!(raw, Tag::Compression, "ARW: Couldn't find Compression").get_u16(0);
    let bps = if camera.bps != 0 {
      camera.bps
    } else {
      fetch_tag!(raw, Tag::BitsPerSample, "ARW: Couldn't find bps").get_u16(0) as u32
    };
    let src = &self.buffer[offset .. self.buffer.len()];

    let image = match compression {
      1 => decode_16le(src, width as usize, height as usize),
      32767 => {
        if ((width*height*bps) as usize) != count*8 {
          ArwDecoder::decode_arw1(src, width, height)
        } else {
          match bps {
            8 => {let curve = try!(ArwDecoder::get_curve(raw)); ArwDecoder::decode_arw2(src, width, height, &curve)},
            12 => decode_12le(src, width as usize, height as usize),
            _ => return Err(format!("ARW2: Don't know how to decode images with {} bps", bps)),
          }
        }
      },
      _ => return Err(format!("ARW: Don't know how to decode type {}", compression).to_string()),
    };

    ok_image(camera, width, height, try!(self.get_wb()), image)
  }
}

impl<'a> ArwDecoder<'a> {
  fn decode_arw1(buf: &[u8], width: u32, height: u32) -> Vec<u16> {
    let mut buffer: Vec<u16> = vec![0; (width*height) as usize];

    buffer[0] = buf[0] as u16; // Shut up the warnings for now

    buffer
  }

  fn decode_arw2(buf: &[u8], width: u32, height: u32, curve: &LookupTable) -> Vec<u16> {
    // Speedup doesn't currently seem worthwhile above 2 threads, probably because
    // of too much copying
    let threads = 2;
    if threads < 2 || height < threads {
      return ArwDecoder::decode_arw2_slice(buf, width, height, &curve);
    }

    let mut heights = Vec::new();
    let split = height/threads;
    let mut height_split = 0;
    for i in 0..threads {
      let start = height_split;
      height_split += split;
      let end = if i == threads-1 {
        height
      } else {
        height_split -1
      };
      heights.push((start, end));
    }

    crossbeam::scope(|scope| {
      let mut handles = Vec::new();
      for (start, end) in heights {
        let src = &buf[((start*width) as usize)..buf.len()];
        let handle = scope.spawn(move || {
          ArwDecoder::decode_arw2_slice(src, width, end-start+1, &curve)
        });
        handles.push(handle);
      }

      let mut out = Vec::new();
      for h in handles {
        let mut other = h.join();
        out.append(&mut other);
      }
      out
    })
  }

  fn decode_arw2_slice(buf: &[u8], width: u32, height: u32, curve: &LookupTable) -> Vec<u16> {
    let mut buffer: Vec<u16> = vec![0; (width*height) as usize];
    let mut pump = BitPump::new(buf);

    for row in 0..height {
      // Process 16 pixels at a time in interleaved fashion
      let mut col = 0;
      let mut random = pump.peek_bits(24);
      while col < (width-30) {
        let max = pump.get_bits(11);
        let min = pump.get_bits(11);
        let imax = pump.get_bits(4);
        let imin = pump.get_bits(4);
        let mut sh = 0;
        while sh<4 && (0x80 << sh) <= (max - min) {sh = sh + 1;}
        for i in 0..16 {
          let val = if i == imax {
            max
          } else if i == imin {
            min
          } else {
            cmp::min(0x7ff,(pump.get_bits(7) << sh) + min)
          };
          buffer[(row*width+col+i*2) as usize] = curve.dither(val as u16, &mut random);
        }
        col += if (col & 1) != 0 {31} else {1};  // Skip to next 16 pixels
      }
    }

    buffer
  }

  fn get_wb(&self) -> Result<[f32;4], String> {
    let priv_offset = fetch_tag!(self.tiff, Tag::DNGPrivateArea, "ARW: Couldn't find private offset").get_u32(0);
    let priv_tiff = TiffIFD::new(self.buffer, priv_offset as usize, 0, 0, LITTLE_ENDIAN);
    let sony_offset = fetch_tag!(priv_tiff, Tag::SonyOffset, "ARW: Couldn't find sony offset").get_u32(0) as usize;
    let sony_length = fetch_tag!(priv_tiff, Tag::SonyLength, "ARW: Couldn't find sony length").get_u32(0) as usize;
    let sony_key = fetch_tag!(priv_tiff, Tag::SonyKey, "ARW: Couldn't find sony key").get_u32(0);
    let decrypted_buf = ArwDecoder::sony_decrypt(self.buffer, sony_offset, sony_length, sony_key);
    let decrypted_tiff = TiffIFD::new(&decrypted_buf, 0, sony_offset, 0, LITTLE_ENDIAN);
    let grgb_levels = decrypted_tiff.find_entry(Tag::SonyGRBG);
    let rggb_levels = decrypted_tiff.find_entry(Tag::SonyRGGB);
    if grgb_levels.is_some() {
      let levels = grgb_levels.unwrap();
      Ok([levels.get_u16(1) as f32, levels.get_u16(0) as f32, levels.get_u16(2) as f32, f32::NAN])
    } else if rggb_levels.is_some() {
      let levels = rggb_levels.unwrap();
      Ok([levels.get_u16(0) as f32, levels.get_u16(1) as f32, levels.get_u16(3) as f32, f32::NAN])
    } else {
      Err("ARW: Couldn't find GRGB or RGGB levels".to_string())
    }
  }

  fn get_curve(raw: &TiffIFD) -> Result<LookupTable, String> {
    let centry = fetch_tag!(raw, Tag::SonyCurve, "ARW: Couldn't find sony curve");
    let mut curve: [u32;6] = [ 0, 0, 0, 0, 0, 4095 ];

    for i in 0..4 {
      curve[i+1] = ((centry.get_u16(i) >> 2) & 0xfff) as u32;
    }

    let mut out = vec![0 as u16; (curve[5]+1) as usize];
    for i in 0..5 {
      for j in (curve[i]+1)..(curve[i+1]+1) {
        out[j as usize] = out[(j-1) as usize] + (1<<i);
      }
    }

    Ok(LookupTable::new(&out))
  }

  fn sony_decrypt(buf: &[u8], offset: usize, length: usize, key: u32) -> Vec<u8>{
    let mut pad: [u32; 128] = [0 as u32; 128];
    let mut mkey = key;
    // Make sure we always have space for the final bytes even if the buffer
    // isn't a multiple of 4
    let mut out = vec![0;length+4];
    // Initialize the decryption pad from the key
    for p in 0..4 {
      mkey = mkey.wrapping_mul(48828125).wrapping_add(1);
      pad[p] = mkey;
    }
    pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
    for p in 4..127 {
      pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;
    }
    for p in 0..127 {
      pad[p] = u32::from_be(pad[p]);
    }

    for i in (0..length).step(4) {
      let p = i/4 + 127;
      pad[p & 127] = pad[(p+1) & 127] ^ pad[(p+1+64) & 127];
      let output = LEu32(buf, offset+i) ^ pad[p & 127];
      let bytes: [u8; 4] = unsafe { transmute(output.to_le()) };
      out[i]   = bytes[0];
      out[i+1] = bytes[1];
      out[i+2] = bytes[2];
      out[i+3] = bytes[3];
    }
    out
  }
}
<commit_msg>ARW: Avoid copying to speedup with ARW2 threading<commit_after>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use std::mem::transmute;
use std::slice;
extern crate itertools;
use self::itertools::Itertools;
extern crate crossbeam;
use std::f32;
use std::cmp;

#[derive(Debug, Clone)]
pub struct ArwDecoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> ArwDecoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> ArwDecoder<'a> {
    ArwDecoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for ArwDecoder<'a> {
  fn identify(&self) -> Result<&Camera, String> {
    let make = fetch_tag!(self.tiff, Tag::Make, "ARW: Couldn't find Make").get_str();
    let model = fetch_tag!(self.tiff, Tag::Model, "ARW: Couldn't find Model").get_str();
    self.rawloader.check_supported(make, model)
  }

  fn image(&self) -> Result<Image,String> {
    let camera = try!(self.identify());
    let data = self.tiff.find_ifds_with_tag(Tag::StripOffsets);
    if data.len() == 0 {
      return Err("ARW: Couldn't find the data IFD!".to_string())
    }
    let raw = data[0];
    let width = fetch_tag!(raw, Tag::ImageWidth, "ARW: Couldn't find width").get_u16(0) as u32;
    let height = fetch_tag!(raw, Tag::ImageLength, "ARW: Couldn't find height").get_u16(0) as u32;
    let offset = fetch_tag!(raw, Tag::StripOffsets, "ARW: Couldn't find offset").get_u32(0) as usize;
    let count = fetch_tag!(raw, Tag::StripByteCounts, "ARW: Couldn't find byte count").get_u32(0) as usize;
    let compression = fetch_tag!(raw, Tag::Compression, "ARW: Couldn't find Compression").get_u16(0);
    let bps = if camera.bps != 0 {
      camera.bps
    } else {
      fetch_tag!(raw, Tag::BitsPerSample, "ARW: Couldn't find bps").get_u16(0) as u32
    };
    let src = &self.buffer[offset .. self.buffer.len()];

    let image = match compression {
      1 => decode_16le(src, width as usize, height as usize),
      32767 => {
        if ((width*height*bps) as usize) != count*8 {
          ArwDecoder::decode_arw1(src, width, height)
        } else {
          match bps {
            8 => {let curve = try!(ArwDecoder::get_curve(raw)); ArwDecoder::decode_arw2(src, width, height, &curve)},
            12 => decode_12le(src, width as usize, height as usize),
            _ => return Err(format!("ARW2: Don't know how to decode images with {} bps", bps)),
          }
        }
      },
      _ => return Err(format!("ARW: Don't know how to decode type {}", compression).to_string()),
    };

    ok_image(camera, width, height, try!(self.get_wb()), image)
  }
}

impl<'a> ArwDecoder<'a> {
  fn decode_arw1(buf: &[u8], width: u32, height: u32) -> Vec<u16> {
    let mut buffer: Vec<u16> = vec![0; (width*height) as usize];

    buffer[0] = buf[0] as u16; // Shut up the warnings for now

    buffer
  }

  fn decode_arw2(buf: &[u8], width: u32, height: u32, curve: &LookupTable) -> Vec<u16> {
    let mut out: Vec<u16> = vec![0; (width*height) as usize];

    // Default to 4 threads as that should be close to the ideal speedup on most
    // machines. In the future we need a way to have this be a parameter or even
    // to set it dynamically based on how loaded the machine is.
    let threads = 4;
    if threads < 2 || height < threads {
      ArwDecoder::decode_arw2_slice(&mut out, buf, width, height, &curve);
      return out
    }

    {
      let mut heights = Vec::new();
      let split = height/threads;
      let mut height_split = 0;
      for i in 0..threads {
        let start = height_split;
        height_split += split;
        let end = if i == threads-1 { height } else { height_split -1 };
        let tall = end-start+1;
        let ptr = (&mut out[(start*width) as usize ..]).as_mut_ptr();
        let out_part = unsafe {
           slice::from_raw_parts_mut(ptr, (tall*width) as usize)
        };
        heights.push((start, tall, out_part));
      }

      crossbeam::scope(|scope| {
        let mut handles = Vec::new();
        for (start, tall, out_part) in heights {
          let src = &buf[((start*width) as usize)..buf.len()];
          let handle = scope.spawn(move || {
            ArwDecoder::decode_arw2_slice(out_part, src, width, tall, &curve)
          });
          handles.push(handle);
        }

        for h in handles { h.join() };
      });
    }
    out
  }

  fn decode_arw2_slice(out: &mut [u16], buf: &[u8], width: u32, height: u32, curve: &LookupTable) {
    let mut pump = BitPump::new(buf);

    for row in 0..height {
      // Process 16 pixels at a time in interleaved fashion
      let mut col = 0;
      let mut random = pump.peek_bits(24);
      while col < (width-30) {
        let max = pump.get_bits(11);
        let min = pump.get_bits(11);
        let imax = pump.get_bits(4);
        let imin = pump.get_bits(4);
        let mut sh = 0;
        while sh<4 && (0x80 << sh) <= (max - min) {sh = sh + 1;}
        for i in 0..16 {
          let val = if i == imax {
            max
          } else if i == imin {
            min
          } else {
            cmp::min(0x7ff,(pump.get_bits(7) << sh) + min)
          };
          out[(row*width+col+i*2) as usize] = curve.dither(val as u16, &mut random);
        }
        col += if (col & 1) != 0 {31} else {1};  // Skip to next 16 pixels
      }
    }
  }

  fn get_wb(&self) -> Result<[f32;4], String> {
    let priv_offset = fetch_tag!(self.tiff, Tag::DNGPrivateArea, "ARW: Couldn't find private offset").get_u32(0);
    let priv_tiff = TiffIFD::new(self.buffer, priv_offset as usize, 0, 0, LITTLE_ENDIAN);
    let sony_offset = fetch_tag!(priv_tiff, Tag::SonyOffset, "ARW: Couldn't find sony offset").get_u32(0) as usize;
    let sony_length = fetch_tag!(priv_tiff, Tag::SonyLength, "ARW: Couldn't find sony length").get_u32(0) as usize;
    let sony_key = fetch_tag!(priv_tiff, Tag::SonyKey, "ARW: Couldn't find sony key").get_u32(0);
    let decrypted_buf = ArwDecoder::sony_decrypt(self.buffer, sony_offset, sony_length, sony_key);
    let decrypted_tiff = TiffIFD::new(&decrypted_buf, 0, sony_offset, 0, LITTLE_ENDIAN);
    let grgb_levels = decrypted_tiff.find_entry(Tag::SonyGRBG);
    let rggb_levels = decrypted_tiff.find_entry(Tag::SonyRGGB);
    if grgb_levels.is_some() {
      let levels = grgb_levels.unwrap();
      Ok([levels.get_u16(1) as f32, levels.get_u16(0) as f32, levels.get_u16(2) as f32, f32::NAN])
    } else if rggb_levels.is_some() {
      let levels = rggb_levels.unwrap();
      Ok([levels.get_u16(0) as f32, levels.get_u16(1) as f32, levels.get_u16(3) as f32, f32::NAN])
    } else {
      Err("ARW: Couldn't find GRGB or RGGB levels".to_string())
    }
  }

  fn get_curve(raw: &TiffIFD) -> Result<LookupTable, String> {
    let centry = fetch_tag!(raw, Tag::SonyCurve, "ARW: Couldn't find sony curve");
    let mut curve: [u32;6] = [ 0, 0, 0, 0, 0, 4095 ];

    for i in 0..4 {
      curve[i+1] = ((centry.get_u16(i) >> 2) & 0xfff) as u32;
    }

    let mut out = vec![0 as u16; (curve[5]+1) as usize];
    for i in 0..5 {
      for j in (curve[i]+1)..(curve[i+1]+1) {
        out[j as usize] = out[(j-1) as usize] + (1<<i);
      }
    }

    Ok(LookupTable::new(&out))
  }

  fn sony_decrypt(buf: &[u8], offset: usize, length: usize, key: u32) -> Vec<u8>{
    let mut pad: [u32; 128] = [0 as u32; 128];
    let mut mkey = key;
    // Make sure we always have space for the final bytes even if the buffer
    // isn't a multiple of 4
    let mut out = vec![0;length+4];
    // Initialize the decryption pad from the key
    for p in 0..4 {
      mkey = mkey.wrapping_mul(48828125).wrapping_add(1);
      pad[p] = mkey;
    }
    pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
    for p in 4..127 {
      pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;
    }
    for p in 0..127 {
      pad[p] = u32::from_be(pad[p]);
    }

    for i in (0..length).step(4) {
      let p = i/4 + 127;
      pad[p & 127] = pad[(p+1) & 127] ^ pad[(p+1+64) & 127];
      let output = LEu32(buf, offset+i) ^ pad[p & 127];
      let bytes: [u8; 4] = unsafe { transmute(output.to_le()) };
      out[i]   = bytes[0];
      out[i+1] = bytes[1];
      out[i+2] = bytes[2];
      out[i+3] = bytes[3];
    }
    out
  }
}
<|endoftext|>


<commit_before>pub enum Flag {
    Set(&'static str),
    Clear(&'static str),
    NotAffected(&'static str),
}

pub struct FlagsDesc {
    pub x: Flag,
    pub n: Flag,
    pub z: Flag,
    pub v: Flag,
    pub c: Flag,
}

const FLAGS_ARC: FlagsDesc = FlagsDesc {
    x: Flag::Set("X - Set the same as carry"),
    n: Flag::Set("N - Set if the result is negative; cleared otherwise."),
    z: Flag::Set("Z — Set if the result is zero; cleared otherwise."),
    v: Flag::Set("V — Set if an overflow is generated; cleared otherwise."),
    c: Flag::Set("C — Set if a carry is generated; cleared otherwise."),
};

pub struct Description {
    pub description: &'static str,
    pub operation: &'static str,
    pub assembler: &'static [&'static str],
    pub attributes: &'static str,
    pub flags: &'static FlagsDesc,
}

pub const ABCD_DESC: Description = Description {
    description: "Adds the source operand to the destination operand along with the extend bit, and stores the result in the destination location. The addition is performed using binary- coded decimal arithmetic. The operands, which are packed binary-coded decimal numbers, can be addressed in two different ways\n
        1. Data Register to Data Register: The operands are contained in the data registers specified in the instruction.\n
        2. Memory to Memory: The operands are addressed with the predecrement addressing mode using the address registers specified in the instruction.\n
        This operation is a byte operation only.",
    operation: "Source10 + Destination10 + X → Destination",
    assembler: &["Add < ea > ,Dn", "Add Dn, < ea >"],
    attributes: "Byte, Word, Long",
    flags: &FLAGS_ALL_SET,
};

pub const ADD_DESC: Description = Description {
    description: "Adds the source operand to the destination operand using binary addition and stores the result in the destination location. The size of the operation may be specified as byte, word, or long. The mode of the instruction indicates which operand is the source and which is the destination, as well as the operand size.",
    operation: "Source + Destination → Destination",
    assembler: &["Add < ea > ,Dn", "Add Dn, < ea >"],
    attributes: "Byte, Word, Long",
    flags: &FLAGS_ARC,
};

<commit_msg>Fixed compile error<commit_after>pub enum Flag {
    Set(&'static str),
    Clear(&'static str),
    NotAffected(&'static str),
    Undefined,
}

pub struct FlagsDesc {
    pub x: Flag,
    pub n: Flag,
    pub z: Flag,
    pub v: Flag,
    pub c: Flag,
}

const FLAGS_ARC: FlagsDesc = FlagsDesc {
    x: Flag::Set("X - Set the same as carry"),
    n: Flag::Set("N - Set if the result is negative; cleared otherwise."),
    z: Flag::Set("Z — Set if the result is zero; cleared otherwise."),
    v: Flag::Set("V — Set if an overflow is generated; cleared otherwise."),
    c: Flag::Set("C — Set if a carry is generated; cleared otherwise."),
};

const FLAGS_ABCD: FlagsDesc = FlagsDesc {
    x: Flag::Set("X - Set the same as carry"),
    n: Flag::Undefined,
    z: Flag::Clear("Z — Cleared if the result is nonzero; unchanged otherwise"),
    v: Flag::Undefined,
    c: Flag::Set("C — Set if a decimal carry was generated; cleared otherwise."),
};

pub struct Description {
    pub description: &'static str,
    pub operation: &'static str,
    pub assembler: &'static [&'static str],
    pub attributes: &'static str,
    pub flags: &'static FlagsDesc,
}

pub const ABCD_DESC: Description = Description {
    description: "Adds the source operand to the destination operand along with the extend bit, and stores the result in the destination location. The addition is performed using binary- coded decimal arithmetic. The operands, which are packed binary-coded decimal numbers, can be addressed in two different ways\n
        1. Data Register to Data Register: The operands are contained in the data registers specified in the instruction.\n
        2. Memory to Memory: The operands are addressed with the predecrement addressing mode using the address registers specified in the instruction.\n
        This operation is a byte operation only.",
    operation: "Source10 + Destination10 + X → Destination",
    assembler: &["Add < ea > ,Dn", "Add Dn, < ea >"],
    attributes: "Byte, Word, Long",
    flags: &FLAGS_ABCD,
};

pub const ADD_DESC: Description = Description {
    description: "Adds the source operand to the destination operand using binary addition and stores the result in the destination location. The size of the operation may be specified as byte, word, or long. The mode of the instruction indicates which operand is the source and which is the destination, as well as the operand size.",
    operation: "Source + Destination → Destination",
    assembler: &["Add < ea > ,Dn", "Add Dn, < ea >"],
    attributes: "Byte, Word, Long",
    flags: &FLAGS_ARC,
};

<|endoftext|>


<commit_before>use elektra_sys::{keyDel, keyDup, keyName, keyNew, keySetName, keySetString};
use std::error::Error;
use std::ffi::{CStr, CString};
use std::fmt;
use std::ptr::NonNull;

#[derive(Debug,PartialEq)]
pub enum KeyError {
    InvalidName,
    TypeMismatch,
    // TypeConversion,
    // NotFoundException
}

impl fmt::Display for KeyError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        match self {
            KeyError::InvalidName => write!(f, "Key has an invalid name"),
            KeyError::TypeMismatch => write!(f, "Binary/String key mismatch, use the appropriate method for your key type, get_string or get_binary"),
            // _ => unimplemented!(),
        }
    }
}

impl Error for KeyError {}

#[derive(Debug)]
pub struct Key {
    ptr: NonNull<elektra_sys::Key>,
}

impl Drop for Key {
    fn drop(&mut self) {
        println!("Drop Key {:?}", self);
        unsafe { keyDel(self.ptr.as_ptr()) };
    }
}

impl Key {
    /// Construct a new empty key
    pub fn new() -> Key {
        let key_ptr = unsafe { keyNew(0 as *const i8) };
        Key::from(key_ptr)
    }

    /// Construct a new key from a raw key pointer
    pub fn from(ptr: *mut elektra_sys::Key) -> Key {
        Key {
            ptr: NonNull::new(ptr).unwrap(),
        }
    }

    /// Set the name of a key. Must adhere to the rules for keynames otherwise an error is returned.
    /// Returns the size in bytes of this new key name including the ending NUL.
    /// # Examples
    /// ```
    /// use elektra::Key;
    /// let mut key = Key::new();
    /// key.set_name("user/test/rust").unwrap();
    /// assert_eq!(key.get_name(), "user/test/rust");
    /// ```
    /// # Panics
    /// Panics if the provided string contains internal nul bytes.
    pub fn set_name(&mut self, name: &str) -> Result<u32, KeyError> {
        let cptr = CString::new(name).unwrap();
        let ret_val = unsafe { keySetName(self.ptr.as_ptr(), cptr.as_ptr()) };

        if ret_val > 0 {
            Ok(ret_val as u32)
        } else {
            Err(KeyError::InvalidName)
        }
    }

    /// Return the name of the key as a borrowed slice.
    pub fn get_name(&self) -> &str {
        let c_str = unsafe { CStr::from_ptr(keyName(self.ptr.as_ref())) };
        c_str.to_str().unwrap()
    }

    // keyvalue methds

    // Omitted keyValue() due to return value of void pointer, which cannot be used safely in Rust

    /// Returns the number of bytes needed to store the key value, including the
    /// NULL terminator.
    pub fn get_value_size(&self) -> usize {
        let ret_val = unsafe { elektra_sys::keyGetValueSize(self.ptr.as_ptr()) };
        // keyGetValueSize returns -1 on null pointers, but we can be sure self.ptr is valid
        // so this conversion is safe
        ret_val as usize
    }

    /// Sets the value of the key to the supplied string.
    /// # Panics
    /// Panics if the provided string contains internal nul bytes.
    pub fn set_string(&mut self, value: &str) {
        let cptr = CString::new(value).unwrap();
        unsafe { keySetString(self.ptr.as_ptr(), cptr.as_ptr()) };
    }

    /// Returns the string value of the key if the type of the key is string, an error if it's binary.
    /// # Panics
    /// Panics if the underlying string cannot be converted to UTF-8.
    pub fn get_string(&self) -> Result<&str, KeyError> {
        if self.is_binary() {
            return Err(KeyError::TypeMismatch);
        }
        let c_str = unsafe { CStr::from_ptr(elektra_sys::keyString(self.ptr.as_ref())) };
        Ok(c_str.to_str().unwrap())
    }

    /// Sets the key's binary content to the supplied data.
    pub fn set_binary(&mut self, data: &[u8]) {
        unsafe {
            elektra_sys::keySetBinary(
                self.ptr.as_ptr(),
                data.as_ptr() as *const std::os::raw::c_void,
                data.len(),
            );
        }
    }

    /// Returns the keys binary content
    /// Returns a TypeMismatch if the key is of type string
    pub fn get_binary(&self) -> Result<Vec<u8>, KeyError> {
        if self.is_string() {
            return Err(KeyError::TypeMismatch);
        }
        let mut vec: Vec<u8> = Vec::with_capacity(self.get_value_size());

        let ret_val = unsafe {
            elektra_sys::keyGetBinary(
                self.ptr.as_ptr(),
                vec.as_mut_ptr() as *mut std::os::raw::c_void,
                vec.capacity(),
            )
        };

        if ret_val >= 0 {
            unsafe { vec.set_len(ret_val as usize) };
            Ok(vec)
        } else {
            // Since the function checks for is_string, a type mismatch is caught earlier
            // So this error can only occur as a result of a logic error in the program
            panic!("maxSize is 0, too small or too large.");
        }
    }

    // keytest methods

    /// Returns true if the key has a binary value.
    pub fn is_binary(&self) -> bool {
        unsafe { elektra_sys::keyIsBinary(self.ptr.as_ptr()) == 1 }
    }

    /// Returns true if the key has a string value.
    pub fn is_string(&self) -> bool {
        unsafe { elektra_sys::keyIsString(self.ptr.as_ptr()) == 1 }
    }

    /// Return a duplicate of the key.
    pub fn duplicate(&self) -> Key {
        let dup_ptr = unsafe { keyDup(self.ptr.as_ptr()) };
        Key::from(dup_ptr)
    }
}

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

    #[test]
    fn can_write_read_key() {
        let key_name = "user/test/key";
        let mut key = Key::new();
        key.set_name(key_name).unwrap();
        assert_eq!(key.get_name(), key_name);
    }

    #[test]
    fn can_write_read_key_value() {
        let key_name = "user/test/key";
        let utf8_value = "😃";
        let mut key = Key::new();
        key.set_name(key_name).unwrap();
        key.set_string(utf8_value);
        assert_eq!(key.get_name(), key_name);
        assert_eq!(key.get_string().unwrap(), utf8_value);
    }

    #[test]
    fn can_duplicate_key() {
        let key_name = "user/test/key";
        let mut key_dup;
        {
            let mut key = Key::new();
            key.set_name(key_name).unwrap();
            key_dup = Some(key.duplicate());
            // key is dropped here
        }
        assert_eq!(key_dup.unwrap().get_name(), key_name);
    }

    #[test]
    fn can_write_read_binary() {
        let mut key = Key::new();
        let binary_content: [u8; 7] = [25, 34, 0, 254, 1, 0, 7];
        key.set_name("user/test/rust").unwrap();
        key.set_binary(&binary_content);
        let read_content = key.get_binary().unwrap();
        assert_eq!(read_content, binary_content);
    }

    #[test]
    fn can_write_read_empty_binary() {
        let mut key = Key::new();
        let binary_content: [u8; 0] = [];
        key.set_name("user/test/binary").unwrap();
        key.set_binary(&binary_content);
        // set_binary does not set binary flag, size is 0
        // so get_binary returns error
        let err = key.get_binary().unwrap_err();
        assert_eq!(err, KeyError::TypeMismatch);
    }
}
<commit_msg>Rust: Implement Equality for Key<commit_after>use elektra_sys::{keyDel, keyDup, keyName, keyNew, keySetName, keySetString};
use std::error::Error;
use std::ffi::{CStr, CString};
use std::fmt;
use std::ptr::NonNull;

#[derive(Debug, PartialEq)]
pub enum KeyError {
    InvalidName,
    TypeMismatch,
    // TypeConversion,
    // NotFoundException
}

impl fmt::Display for KeyError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        match self {
            KeyError::InvalidName => write!(f, "Key has an invalid name"),
            KeyError::TypeMismatch => write!(f, "Binary/String key mismatch, use the appropriate method for your key type, get_string or get_binary"),
            // _ => unimplemented!(),
        }
    }
}

impl Error for KeyError {}

#[derive(Debug)]
pub struct Key {
    ptr: NonNull<elektra_sys::Key>,
}

impl Drop for Key {
    fn drop(&mut self) {
        println!("Drop Key {:?}", self);
        unsafe { keyDel(self.ptr.as_ptr()) };
    }
}

impl PartialEq for Key {
    fn eq(&self, other: &Self) -> bool {
        unsafe {
            elektra_sys::keyCmp(
                self.ptr.as_ptr() as *const elektra_sys::Key,
                other.ptr.as_ptr() as *const elektra_sys::Key,
            ) == 0
        }
    }
}

impl Eq for Key {}

impl Key {
    /// Construct a new empty key
    pub fn new() -> Key {
        let key_ptr = unsafe { keyNew(0 as *const i8) };
        Key::from(key_ptr)
    }

    /// Construct a new key from a raw key pointer
    pub fn from(ptr: *mut elektra_sys::Key) -> Key {
        Key {
            ptr: NonNull::new(ptr).unwrap(),
        }
    }

    /// Set the name of a key. Must adhere to the rules for keynames otherwise an error is returned.
    /// Returns the size in bytes of this new key name including the ending NUL.
    /// # Examples
    /// ```
    /// use elektra::Key;
    /// let mut key = Key::new();
    /// key.set_name("user/test/rust").unwrap();
    /// assert_eq!(key.get_name(), "user/test/rust");
    /// ```
    /// # Panics
    /// Panics if the provided string contains internal nul bytes.
    pub fn set_name(&mut self, name: &str) -> Result<u32, KeyError> {
        let cptr = CString::new(name).unwrap();
        let ret_val = unsafe { keySetName(self.ptr.as_ptr(), cptr.as_ptr()) };

        if ret_val > 0 {
            Ok(ret_val as u32)
        } else {
            Err(KeyError::InvalidName)
        }
    }

    /// Return the name of the key as a borrowed slice.
    pub fn get_name(&self) -> &str {
        let c_str = unsafe { CStr::from_ptr(keyName(self.ptr.as_ref())) };
        c_str.to_str().unwrap()
    }

    // keyvalue methds

    // Omitted keyValue() due to return value of void pointer, which cannot be used safely in Rust

    /// Returns the number of bytes needed to store the key value, including the
    /// NULL terminator.
    pub fn get_value_size(&self) -> usize {
        let ret_val = unsafe { elektra_sys::keyGetValueSize(self.ptr.as_ptr()) };
        // keyGetValueSize returns -1 on null pointers, but we can be sure self.ptr is valid
        // so this conversion is safe
        ret_val as usize
    }

    /// Sets the value of the key to the supplied string.
    /// # Panics
    /// Panics if the provided string contains internal nul bytes.
    pub fn set_string(&mut self, value: &str) {
        let cptr = CString::new(value).unwrap();
        unsafe { keySetString(self.ptr.as_ptr(), cptr.as_ptr()) };
    }

    /// Returns the string value of the key if the type of the key is string, an error if it's binary.
    /// # Panics
    /// Panics if the underlying string cannot be converted to UTF-8.
    pub fn get_string(&self) -> Result<&str, KeyError> {
        if self.is_binary() {
            return Err(KeyError::TypeMismatch);
        }
        let c_str = unsafe { CStr::from_ptr(elektra_sys::keyString(self.ptr.as_ref())) };
        Ok(c_str.to_str().unwrap())
    }

    /// Sets the key's binary content to the supplied data.
    pub fn set_binary(&mut self, data: &[u8]) {
        unsafe {
            elektra_sys::keySetBinary(
                self.ptr.as_ptr(),
                data.as_ptr() as *const std::os::raw::c_void,
                data.len(),
            );
        }
    }

    /// Returns the keys binary content
    /// Returns a TypeMismatch if the key is of type string
    pub fn get_binary(&self) -> Result<Vec<u8>, KeyError> {
        if self.is_string() {
            return Err(KeyError::TypeMismatch);
        }
        let mut vec: Vec<u8> = Vec::with_capacity(self.get_value_size());

        let ret_val = unsafe {
            elektra_sys::keyGetBinary(
                self.ptr.as_ptr(),
                vec.as_mut_ptr() as *mut std::os::raw::c_void,
                vec.capacity(),
            )
        };

        if ret_val >= 0 {
            unsafe { vec.set_len(ret_val as usize) };
            Ok(vec)
        } else {
            // Since the function checks for is_string, a type mismatch is caught earlier
            // So this error can only occur as a result of a logic error in the program
            panic!("maxSize is 0, too small or too large.");
        }
    }

    // keytest methods

    /// Returns true if the key has a binary value.
    pub fn is_binary(&self) -> bool {
        unsafe { elektra_sys::keyIsBinary(self.ptr.as_ptr()) == 1 }
    }

    /// Returns true if the key has a string value.
    pub fn is_string(&self) -> bool {
        unsafe { elektra_sys::keyIsString(self.ptr.as_ptr()) == 1 }
    }

    /// Return a duplicate of the key.
    pub fn duplicate(&self) -> Key {
        let dup_ptr = unsafe { keyDup(self.ptr.as_ptr()) };
        Key::from(dup_ptr)
    }
}

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

    #[test]
    fn can_write_read_key() {
        let key_name = "user/test/key";
        let mut key = Key::new();
        key.set_name(key_name).unwrap();
        assert_eq!(key.get_name(), key_name);
    }

    #[test]
    fn can_write_read_key_value() {
        let key_name = "user/test/key";
        let utf8_value = "😃";
        let mut key = Key::new();
        key.set_name(key_name).unwrap();
        key.set_string(utf8_value);
        assert_eq!(key.get_name(), key_name);
        assert_eq!(key.get_string().unwrap(), utf8_value);
    }

    #[test]
    fn can_duplicate_key() {
        let key_name = "user/test/key";
        let mut key_dup;
        {
            let mut key = Key::new();
            key.set_name(key_name).unwrap();
            key_dup = Some(key.duplicate());
            // key is dropped here
        }
        assert_eq!(key_dup.unwrap().get_name(), key_name);
    }

    #[test]
    fn can_write_read_binary() {
        let mut key = Key::new();
        let binary_content: [u8; 7] = [25, 34, 0, 254, 1, 0, 7];
        key.set_name("user/test/rust").unwrap();
        key.set_binary(&binary_content);
        let read_content = key.get_binary().unwrap();
        assert_eq!(read_content, binary_content);
    }
    #[test]
    fn can_write_read_empty_binary() {
        let mut key = Key::new();
        let binary_content: [u8; 0] = [];
        key.set_name("user/test/binary").unwrap();
        key.set_binary(&binary_content);
        // set_binary does not set binary flag, size is 0
        // so get_binary returns error
        let err = key.get_binary().unwrap_err();
        assert_eq!(err, KeyError::TypeMismatch);
    }

    #[test]
    fn equality_is_exclusive() {
        let mut key = Key::new();
        key.set_name("user/test/exclusive").unwrap();
        let mut key2 = Key::new();
        key2.set_name("dir/test/exclusive").unwrap();

        assert!(!(key != key));
        assert!(key == key);

        assert!(!(key == key2));
        assert!(key != key2);
    }

    #[test]
    fn equality_is_reflexive() {
        let mut key = Key::new();
        key.set_name("user/test/reflexive").unwrap();
        assert!(key == key);
    }

    #[test]
    fn equality_is_symmetric() {
        let mut key = Key::new();
        key.set_name("user/test/symmetric").unwrap();
        let mut key_dup = Key::new();
        key_dup.set_name("user/test/symmetric").unwrap();

        assert!(key_dup == key);
        assert!(key == key_dup);
    }

    #[test]
    fn equality_is_transitive() {
        let mut key = Key::new();
        key.set_name("user/test/transitive").unwrap();

        let mut key2 = Key::new();
        key2.set_name("user/test/transitive").unwrap();

        let mut key3 = Key::new();
        key3.set_name("user/test/transitive").unwrap();
        assert!(key == key2);
        assert!(key2 == key3);
        assert!(key == key3);
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::io::{BufRead, BufReader, Error, ErrorKind, Result};
use std::net::TcpStream;
use std::thread;
use std::time::Duration;

use crossbeam_channel::{unbounded, Receiver, Sender};

use crate::network::NetworkConnection;
use crate::proto::RawMessage;

pub trait IrcWriter {
    fn write_message(&mut self, msg: &RawMessage) -> Result<()>;
}

pub trait IrcReader {
    fn read_message(&mut self) -> Result<RawMessage>;
}

impl<T: Write> IrcWriter for T {
    fn write_message(&mut self, msg: &RawMessage) -> Result<()> {
        let msg_str = msg.to_string();
        self.write_all(msg_str.as_bytes())?;
        self.write_all(b"\r\n")?;

        Ok(())
    }
}

impl<T: BufRead> IrcReader for T {
    fn read_message(&mut self) -> Result<RawMessage> {
        let mut buf = String::new();
        self.read_line(&mut buf)?;

        let line = buf.trim_end_matches(|c| c == '\r' || c == '\n');
        RawMessage::parse(line).ok_or_else(|| {
            Error::new(ErrorKind::Other, "failed to parse message from line")
        })
    }
}

#[derive(Clone)]
pub struct IrcChannel(pub Sender<RawMessage>);

impl IrcChannel {
    pub fn new() -> (Self, Receiver<RawMessage>) {
        let (sender, receiver) = unbounded();
        (IrcChannel(sender), receiver)
    }
}

impl IrcWriter for IrcChannel {
    fn write_message(&mut self, msg: &RawMessage) -> Result<()> {
        if let Err(err) = self.0.send(msg.clone()) {
            println!("Failed to write to client: {:?}", err);
            return Err(Error::new(ErrorKind::Other, "other end disconnected"));
        }
        Ok(())
    }
}

pub struct IrcSocketConfig<'a> {
    pub nick: &'a str,
    pub addr: &'a str,
    pub max_retries: Option<usize>,
}

pub struct IrcSocket<'a> {
    config: IrcSocketConfig<'a>,

    to_network: (Sender<RawMessage>, Receiver<RawMessage>),
    to_users: (Sender<RawMessage>, Receiver<RawMessage>),
    from_network: (Sender<RawMessage>, Receiver<RawMessage>),
    new_user: (Sender<IrcChannel>, Receiver<IrcChannel>),
}

impl<'a> IrcSocket<'a> {
    pub fn new(config: IrcSocketConfig<'a>) -> Self {
        Self {
            config,

            to_network: unbounded(),
            to_users: unbounded(),
            from_network: unbounded(),
            new_user: unbounded(),
        }
    }

    pub fn network_channel(&self) -> Sender<RawMessage> {
        self.to_network.0.clone()
    }

    pub fn new_user_channel(&self) -> Sender<IrcChannel> {
        self.new_user.0.clone()
    }

    // TODO: this is kind of gross, clean this up
    fn create_stream(&self) -> Result<TcpStream> {
        let _create_stream = || {
            let stream = TcpStream::connect(self.config.addr)?;
            stream.set_read_timeout(Some(Duration::from_secs(180)))?;
            Ok(stream)
        };

        let max_retries = self.config.max_retries;

        let mut i = 0;
        loop {
            let stream = _create_stream();
            let over_max_tries = max_retries.map(|max| i > max).unwrap_or(false);

            if stream.is_ok() || over_max_tries {
                return stream;
            }

            i += 1
        }
    }

    /// On connection close, return `true` when the connection should
    /// be restarted, and false otherwise. If there is a
    /// non-recoverable exception, return the error.
    ///
    /// TODO: Need to come up with the clean exit concept.
    fn connect(&self, users: &mut dyn IrcWriter) -> Result<bool> {
        let from_net_sender = self.from_network.0.clone();

        let mut network = NetworkConnection::new(
            self.config.nick,
            self.to_network.0.clone(),
            self.to_users.0.clone(),
        );

        let stream = self.create_stream()?;
        let mut write_stream = stream.try_clone().expect("clone failed");

        let recv_err = || Error::new(ErrorKind::Other, "receiver disconnected");

        thread::spawn(move || {
            let mut reader = BufReader::new(stream);
            loop {
                let result = reader
                    .read_message()
                    .and_then(|msg| from_net_sender.send(msg).map_err(|_| recv_err()));

                if let Err(err) = result {
                    println!("Read from network failed: {:?}", err);
                    break;
                }
            }
        });

        if network.initialize().is_err() {
            return Ok(true);
        }

        loop {
            let result = crossbeam_channel::select! {
                recv(self.from_network.1) -> msg => {
                    msg.map_err(|_| recv_err())
                        .and_then(|msg| {
                            println!("[birch <- \u{1b}[37;1mnet\u{1b}[0m] {}", msg);
                            network.handle(&msg)
                        })
                },
                recv(self.to_network.1) -> msg => {
                    msg.map_err(|_| recv_err())
                        .and_then(|msg| {
                            println!("[\u{1b}[37;1mbirch\u{1b}[0m -> net] {}", msg);
                            write_stream.write_message(&msg)
                        })
                },
                recv(self.to_users.1) -> msg => {
                    msg.map_err(|_| recv_err()).and_then(|msg| {
                        users.write_message(&msg)
                    })
                },
                recv(self.new_user.1) -> chan => {
                    chan.map_err(|_| recv_err()).and_then(|mut chan| {
                        network.state.welcome_user(&mut chan)
                    })
                },
                // If we haven't received ANYTHING in 4 minutes,
                // network connection likely failed.
                // TODO: this is a jank way of doing this.
                default(Duration::from_secs(240)) => {
                    println!("no network activity in 240 seconds...");
                    break
                }
            };

            if let Err(err) = result {
                println!("read failed: {}", err);
                break;
            }
        }

        Ok(true)
    }

    pub fn start_loop(&mut self, users: &mut dyn IrcWriter) -> Result<()> {
        loop {
            match self.connect(users) {
                Ok(true) => println!("connection terminated, restarting"),
                Ok(false) => break,
                Err(err) => {
                    println!("connection failed: {:?}", err);
                    return Err(err);
                }
            }
        }
        Ok(())
    }
}
<commit_msg>Reuse same NetworkConnection instance<commit_after>use std::io::prelude::*;
use std::io::{BufRead, BufReader, Error, ErrorKind, Result};
use std::net::TcpStream;
use std::thread;
use std::time::Duration;

use crossbeam_channel::{unbounded, Receiver, Sender};

use crate::network::NetworkConnection;
use crate::proto::RawMessage;

pub trait IrcWriter {
    fn write_message(&mut self, msg: &RawMessage) -> Result<()>;
}

pub trait IrcReader {
    fn read_message(&mut self) -> Result<RawMessage>;
}

impl<T: Write> IrcWriter for T {
    fn write_message(&mut self, msg: &RawMessage) -> Result<()> {
        let msg_str = msg.to_string();
        self.write_all(msg_str.as_bytes())?;
        self.write_all(b"\r\n")?;

        Ok(())
    }
}

impl<T: BufRead> IrcReader for T {
    fn read_message(&mut self) -> Result<RawMessage> {
        let mut buf = String::new();
        self.read_line(&mut buf)?;

        let line = buf.trim_end_matches(|c| c == '\r' || c == '\n');
        RawMessage::parse(line).ok_or_else(|| {
            Error::new(ErrorKind::Other, "failed to parse message from line")
        })
    }
}

#[derive(Clone)]
pub struct IrcChannel(pub Sender<RawMessage>);

impl IrcChannel {
    pub fn new() -> (Self, Receiver<RawMessage>) {
        let (sender, receiver) = unbounded();
        (IrcChannel(sender), receiver)
    }
}

impl IrcWriter for IrcChannel {
    fn write_message(&mut self, msg: &RawMessage) -> Result<()> {
        if let Err(err) = self.0.send(msg.clone()) {
            println!("Failed to write to client: {:?}", err);
            return Err(Error::new(ErrorKind::Other, "other end disconnected"));
        }
        Ok(())
    }
}

pub struct IrcSocketConfig<'a> {
    pub nick: &'a str,
    pub addr: &'a str,
    pub max_retries: Option<usize>,
}

pub struct IrcSocket<'a> {
    config: IrcSocketConfig<'a>,
    network: NetworkConnection,

    to_network: (Sender<RawMessage>, Receiver<RawMessage>),
    to_users: (Receiver<RawMessage>),
    new_user: (Sender<IrcChannel>, Receiver<IrcChannel>),
}

impl<'a> IrcSocket<'a> {
    pub fn new(config: IrcSocketConfig<'a>) -> Self {
        let to_network = unbounded();
        let to_users = unbounded();

        let network =
            NetworkConnection::new(config.nick, to_network.0.clone(), to_users.0);

        Self {
            config,
            network,

            to_network,
            to_users: to_users.1,
            new_user: unbounded(),
        }
    }

    pub fn network_channel(&self) -> Sender<RawMessage> {
        self.to_network.0.clone()
    }

    pub fn new_user_channel(&self) -> Sender<IrcChannel> {
        self.new_user.0.clone()
    }

    // TODO: this is kind of gross, clean this up
    fn create_stream(&self) -> Result<TcpStream> {
        let _create_stream = || {
            let stream = TcpStream::connect(self.config.addr)?;
            stream.set_read_timeout(Some(Duration::from_secs(180)))?;
            Ok(stream)
        };

        let max_retries = self.config.max_retries;

        let mut i = 0;
        loop {
            let stream = _create_stream();
            let over_max_tries = max_retries.map(|max| i > max).unwrap_or(false);

            if stream.is_ok() || over_max_tries {
                return stream;
            }

            // TODO: Probably want a sleep / exponential back off here.
            i += 1
        }
    }

    /// On connection close, return `true` when the connection should
    /// be restarted, and false otherwise. If there is a
    /// non-recoverable exception, return the error.
    ///
    /// TODO: Need to come up with the clean exit concept.
    fn connect(&mut self, users: &mut dyn IrcWriter) -> Result<bool> {
        let (from_net_sender, from_net_receiver) = unbounded();

        let stream = self.create_stream()?;
        let mut write_stream = stream.try_clone().expect("clone failed");

        let recv_err = || Error::new(ErrorKind::Other, "receiver disconnected");

        thread::spawn(move || {
            let mut reader = BufReader::new(stream);
            loop {
                let result = reader
                    .read_message()
                    .and_then(|msg| from_net_sender.send(msg).map_err(|_| recv_err()));

                if let Err(err) = result {
                    println!("Read from network failed: {:?}", err);
                    break;
                }
            }
        });

        if self.network.initialize().is_err() {
            return Ok(true);
        }

        loop {
            let result = crossbeam_channel::select! {
                recv(from_net_receiver) -> msg => {
                    msg.map_err(|_| recv_err())
                        .and_then(|msg| {
                            println!("[birch <- \u{1b}[37;1mnet\u{1b}[0m] {}", msg);
                            self.network.handle(&msg)
                        })
                },
                recv(self.to_network.1) -> msg => {
                    msg.map_err(|_| recv_err())
                        .and_then(|msg| {
                            println!("[\u{1b}[37;1mbirch\u{1b}[0m -> net] {}", msg);
                            write_stream.write_message(&msg)
                        })
                },
                recv(self.to_users) -> msg => {
                    msg.map_err(|_| recv_err()).and_then(|msg| {
                        users.write_message(&msg)
                    })
                },
                recv(self.new_user.1) -> chan => {
                    chan.map_err(|_| recv_err()).and_then(|mut chan| {
                        self.network.state.welcome_user(&mut chan)
                    })
                },
                // If we haven't received ANYTHING in 4 minutes,
                // network connection likely failed.
                // TODO: this is a jank way of doing this.
                default(Duration::from_secs(240)) => {
                    println!("no network activity in 240 seconds...");
                    break
                }
            };

            if let Err(err) = result {
                println!("read failed: {}", err);
                break;
            }
        }

        Ok(true)
    }

    pub fn start_loop(&mut self, users: &mut dyn IrcWriter) -> Result<()> {
        loop {
            match self.connect(users) {
                Ok(true) => println!("connection terminated, restarting"),
                Ok(false) => break,
                Err(err) => {
                    println!("connection failed: {:?}", err);
                    return Err(err);
                }
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>//
// sprocketnes/util.rs
//
// Author: Patrick Walton
//

use std::cast::transmute;
use std::io::File;
use std::libc::{c_int, c_void, time_t};
use std::ptr::null;

//
// A tiny custom serialization infrastructure, used for savestates.
//
// TODO: Use the standard library's ToBytes and add a FromBytes -- or don't; this is such a small
// amount of code it barely seems worth it.
//

pub trait Save {
    fn save(&mut self, fd: &mut File);
    fn load(&mut self, fd: &mut File);
}

impl Save for u8 {
    fn save(&mut self, fd: &mut File) { fd.write([ *self ]) }
    fn load(&mut self, fd: &mut File) { let mut buf = [ 0 ]; fd.read(buf); *self = buf[0]; }
}

impl Save for u16 {
    fn save(&mut self, fd: &mut File) { fd.write([ *self as u8, (*self >> 8) as u8 ]) }
    fn load(&mut self, fd: &mut File) {
        let mut buf = [ 0, 0 ];
        fd.read(buf);
        *self = (buf[0] as u16) | ((buf[1] as u16) << 8);
    }
}

impl Save for u64 {
    fn save(&mut self, fd: &mut File) {
        let mut buf = [ 0, ..8 ];
        for i in range(0, 8) {
            buf[i] = ((*self) >> (i * 8)) as u8;
        }
        fd.write(buf);
    }
    fn load(&mut self, fd: &mut File) {
        let mut buf = [ 0, ..8 ];
        fd.read(buf);
        *self = 0;
        for i in range(0, 8) {
            *self = *self | (buf[i] as u64 << (i * 8));
        }
    }
}

impl<'a> Save for &'a mut [u8] {
    fn save(&mut self, fd: &mut File) {
        // FIXME: Unsafe due to stupid borrow check bug.
        unsafe {
            let x: &(&[u8]) = transmute(self);
            fd.write(*x);
        }
    }
    fn load(&mut self, fd: &mut File) {
        fd.read(*self);
    }
}

impl Save for bool {
    fn save(&mut self, fd: &mut File) { fd.write([ if *self { 0 } else { 1 } ]) }
    fn load(&mut self, fd: &mut File) {
        let mut val: [u8, ..1] = [ 0 ];
        fd.read(val);
        *self = val[0] != 0
    }
}

// A convenience macro to save and load entire structs.
macro_rules! save_struct(
    ($name:ident { $($field:ident),* }) => (
        impl Save for $name {
            fn save(&mut self, fd: &mut File) {
                $(self.$field.save(fd);)*
            }
            fn load(&mut self, fd: &mut File) {
                $(self.$field.load(fd);)*
            }
        }
    )
)

macro_rules! save_enum(
    ($name:ident { $val_0:ident, $val_1:ident }) => (
        impl Save for $name {
            fn save(&mut self, fd: &mut File) {
                let mut val: u8 = match *self { $val_0 => 0, $val_1 => 1 };
                val.save(fd)
            }
            fn load(&mut self, fd: &mut File) {
                let mut val: u8 = 0;
                val.load(fd);
                *self = if val == 0 { $val_0 } else { $val_1 };
            }
        }
    )
)

//
// Random number generation
//

pub struct Xorshift {
    x: u32,
    y: u32,
    z: u32,
    w: u32,
}

impl Xorshift {
    pub fn new() -> Xorshift {
        Xorshift { x: 123456789, y: 362436069, z: 521288629, w: 88675123 }
    }

    pub fn next(&mut self) -> u32 {
        let t = self.x ^ (self.x << 11);
        self.x = self.y; self.y = self.z; self.z = self.w;
        self.w = self.w ^ (self.w >> 19) ^ (t ^ (t >> 8));
        self.w
    }
}

//
// Simple assertions
//

#[cfg(debug)]
pub fn debug_assert(cond: bool, msg: &str) {
    if !cond {
        println(msg);
    }
}

#[cfg(not(debug))]
pub fn debug_assert(_: bool, _: &str) {}

#[cfg(debug)]
pub fn debug_print(msg: &str) {
    println(msg);
}

#[cfg(not(debug))]
pub fn debug_print(_: &str) {}

//
// Bindings for `gettimeofday(2)`
//

struct timeval {
    tv_sec: time_t,
    tv_usec: u32,
}

extern {
    fn gettimeofday(tp: *mut timeval, tzp: *c_void) -> c_int;
}

pub fn current_time_millis() -> u64 {
    unsafe {
        let mut tv = timeval { tv_sec: 0, tv_usec: 0 };
        gettimeofday(&mut tv, null());
        (tv.tv_sec as u64) * 1000 + (tv.tv_usec as u64) / 1000
    }
}

<commit_msg>Borrow check bug is fixed! One less unsafe<commit_after>//
// sprocketnes/util.rs
//
// Author: Patrick Walton
//

use std::io::File;
use std::libc::{c_int, c_void, time_t};
use std::ptr::null;

//
// A tiny custom serialization infrastructure, used for savestates.
//
// TODO: Use the standard library's ToBytes and add a FromBytes -- or don't; this is such a small
// amount of code it barely seems worth it.
//

pub trait Save {
    fn save(&mut self, fd: &mut File);
    fn load(&mut self, fd: &mut File);
}

impl Save for u8 {
    fn save(&mut self, fd: &mut File) { fd.write([ *self ]) }
    fn load(&mut self, fd: &mut File) { let mut buf = [ 0 ]; fd.read(buf); *self = buf[0]; }
}

impl Save for u16 {
    fn save(&mut self, fd: &mut File) { fd.write([ *self as u8, (*self >> 8) as u8 ]) }
    fn load(&mut self, fd: &mut File) {
        let mut buf = [ 0, 0 ];
        fd.read(buf);
        *self = (buf[0] as u16) | ((buf[1] as u16) << 8);
    }
}

impl Save for u64 {
    fn save(&mut self, fd: &mut File) {
        let mut buf = [ 0, ..8 ];
        for i in range(0, 8) {
            buf[i] = ((*self) >> (i * 8)) as u8;
        }
        fd.write(buf);
    }
    fn load(&mut self, fd: &mut File) {
        let mut buf = [ 0, ..8 ];
        fd.read(buf);
        *self = 0;
        for i in range(0, 8) {
            *self = *self | (buf[i] as u64 << (i * 8));
        }
    }
}

impl<'a> Save for &'a mut [u8] {
    fn save(&mut self, fd: &mut File) {
        fd.write(*self);
    }
    fn load(&mut self, fd: &mut File) {
        fd.read(*self);
    }
}

impl Save for bool {
    fn save(&mut self, fd: &mut File) { fd.write([ if *self { 0 } else { 1 } ]) }
    fn load(&mut self, fd: &mut File) {
        let mut val: [u8, ..1] = [ 0 ];
        fd.read(val);
        *self = val[0] != 0
    }
}

// A convenience macro to save and load entire structs.
macro_rules! save_struct(
    ($name:ident { $($field:ident),* }) => (
        impl Save for $name {
            fn save(&mut self, fd: &mut File) {
                $(self.$field.save(fd);)*
            }
            fn load(&mut self, fd: &mut File) {
                $(self.$field.load(fd);)*
            }
        }
    )
)

macro_rules! save_enum(
    ($name:ident { $val_0:ident, $val_1:ident }) => (
        impl Save for $name {
            fn save(&mut self, fd: &mut File) {
                let mut val: u8 = match *self { $val_0 => 0, $val_1 => 1 };
                val.save(fd)
            }
            fn load(&mut self, fd: &mut File) {
                let mut val: u8 = 0;
                val.load(fd);
                *self = if val == 0 { $val_0 } else { $val_1 };
            }
        }
    )
)

//
// Random number generation
//

pub struct Xorshift {
    x: u32,
    y: u32,
    z: u32,
    w: u32,
}

impl Xorshift {
    pub fn new() -> Xorshift {
        Xorshift { x: 123456789, y: 362436069, z: 521288629, w: 88675123 }
    }

    pub fn next(&mut self) -> u32 {
        let t = self.x ^ (self.x << 11);
        self.x = self.y; self.y = self.z; self.z = self.w;
        self.w = self.w ^ (self.w >> 19) ^ (t ^ (t >> 8));
        self.w
    }
}

//
// Simple assertions
//

#[cfg(debug)]
pub fn debug_assert(cond: bool, msg: &str) {
    if !cond {
        println(msg);
    }
}

#[cfg(not(debug))]
pub fn debug_assert(_: bool, _: &str) {}

#[cfg(debug)]
pub fn debug_print(msg: &str) {
    println(msg);
}

#[cfg(not(debug))]
pub fn debug_print(_: &str) {}

//
// Bindings for `gettimeofday(2)`
//

struct timeval {
    tv_sec: time_t,
    tv_usec: u32,
}

extern {
    fn gettimeofday(tp: *mut timeval, tzp: *c_void) -> c_int;
}

pub fn current_time_millis() -> u64 {
    unsafe {
        let mut tv = timeval { tv_sec: 0, tv_usec: 0 };
        gettimeofday(&mut tv, null());
        (tv.tv_sec as u64) * 1000 + (tv.tv_usec as u64) / 1000
    }
}

<|endoftext|>


<commit_before>// Copyright 2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use libc::c_void;

use gobject_ffi::{self, GCallback};
use translate::ToGlibPtr;

pub unsafe fn connect(receiver: *mut c_void, signal_name: &str, trampoline: GCallback,
                      closure: *mut Box<Fn() + 'static>) -> u64 {
    let handle = gobject_ffi::g_signal_connect_data(receiver, signal_name.to_glib_none().0,
        trampoline, closure as *mut _, Some(destroy_closure),
        gobject_ffi::GConnectFlags::empty()) as u64;
    assert!(handle > 0);
    handle
}

unsafe extern "C" fn destroy_closure(ptr: *mut c_void, _: *mut gobject_ffi::GClosure) {
    let ptr = ptr as *mut Box<Fn()>;
    // destroy
    //Box::from_raw(ptr);
    // from_raw API stability workaround
    let _: Box<Box<Fn()>> = ::std::mem::transmute(ptr);
}
<commit_msg>Change the signal connection receiver to `*mut GObject`<commit_after>// Copyright 2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use libc::c_void;

use gobject_ffi::{self, GCallback};
use translate::ToGlibPtr;

pub unsafe fn connect(receiver: *mut gobject_ffi::GObject, signal_name: &str, trampoline: GCallback,
                      closure: *mut Box<Fn() + 'static>) -> u64 {
    let handle = gobject_ffi::g_signal_connect_data(receiver as *mut _, signal_name.to_glib_none().0,
        trampoline, closure as *mut _, Some(destroy_closure),
        gobject_ffi::GConnectFlags::empty()) as u64;
    assert!(handle > 0);
    handle
}

unsafe extern "C" fn destroy_closure(ptr: *mut c_void, _: *mut gobject_ffi::GClosure) {
    let ptr = ptr as *mut Box<Fn()>;
    // destroy
    //Box::from_raw(ptr);
    // from_raw API stability workaround
    let _: Box<Box<Fn()>> = ::std::mem::transmute(ptr);
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt;
use std::io;
use std::mem;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
#[cfg(target_os = "redox")]
use libc::c_int;
#[cfg(unix)]
use libc::c_int;
#[cfg(windows)]
use winapi::ctypes::c_int;

use sys;
use sys::c;

pub struct Socket {
    inner: sys::Socket,
}

impl Socket {
    pub fn new(family: c_int, ty: c_int) -> io::Result<Socket> {
        Ok(Socket { inner: try!(sys::Socket::new(family, ty)) })
    }

    pub fn bind(&self, addr: &SocketAddr) -> io::Result<()> {
        #[cfg(not(all(any(target_arch = "aarch64", target_arch = "x86_64"), target_os = "android")))]
        use sys::c::socklen_t as len_t;
        #[cfg(all(any(target_arch = "aarch64", target_arch = "x86_64"), target_os = "android"))]
        use libc::c_int as len_t;

        let (addr, len) = addr2raw(addr);
        unsafe {
            ::cvt(c::bind(self.inner.raw(), addr, len as len_t)).map(|_| ())
        }
    }

    pub fn listen(&self, backlog: i32) -> io::Result<()> {
        unsafe {
            ::cvt(c::listen(self.inner.raw(), backlog)).map(|_| ())
        }
    }

    pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
        let (addr, len) = addr2raw(addr);
        unsafe {
            ::cvt(c::connect(self.inner.raw(), addr, len)).map(|_| ())
        }
    }

    pub fn getsockname(&self) -> io::Result<SocketAddr> {
        unsafe {
            let mut storage: c::sockaddr_storage = mem::zeroed();
            let mut len = mem::size_of_val(&storage) as c::socklen_t;
            try!(::cvt(c::getsockname(self.inner.raw(),
                                      &mut storage as *mut _ as *mut _,
                                      &mut len)));
            raw2addr(&storage, len)
        }
    }
}

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

impl ::AsInner for Socket {
    type Inner = sys::Socket;
    fn as_inner(&self) -> &sys::Socket { &self.inner }
}

impl ::FromInner for Socket {
    type Inner = sys::Socket;
    fn from_inner(sock: sys::Socket) -> Socket {
        Socket { inner: sock }
    }
}

impl ::IntoInner for Socket {
    type Inner = sys::Socket;
    fn into_inner(self) -> sys::Socket { self.inner }
}

fn addr2raw(addr: &SocketAddr) -> (*const c::sockaddr, c::socklen_t) {
    match *addr {
        SocketAddr::V4(ref a) => {
            (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t)
        }
        SocketAddr::V6(ref a) => {
            (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t)
        }
    }
}

fn raw2addr(storage: &c::sockaddr_storage, len: c::socklen_t) -> io::Result<SocketAddr> {
    match storage.ss_family as c_int {
        c::AF_INET => {
            unsafe {
                assert!(len as usize >= mem::size_of::<c::sockaddr_in>());
                let sa = storage as *const _ as *const c::sockaddr_in;
                let bits = c::sockaddr_in_u32(&(*sa));
                let ip = Ipv4Addr::new((bits >> 24) as u8,
                                       (bits >> 16) as u8,
                                       (bits >> 8) as u8,
                                       bits as u8);
                Ok(SocketAddr::V4(SocketAddrV4::new(ip, ::ntoh((*sa).sin_port))))
            }
        }
        c::AF_INET6 => {
            unsafe {
                assert!(len as usize >= mem::size_of::<c::sockaddr_in6>());

                let sa = storage as *const _ as *const c::sockaddr_in6;
                #[cfg(windows)]      let arr = (*sa).sin6_addr.u.Byte();
                #[cfg(not(windows))] let arr = (*sa).sin6_addr.s6_addr;

                let ip = Ipv6Addr::new(
                    (arr[0] as u16) << 8 | (arr[1] as u16),
                    (arr[2] as u16) << 8 | (arr[3] as u16),
                    (arr[4] as u16) << 8 | (arr[5] as u16),
                    (arr[6] as u16) << 8 | (arr[7] as u16),
                    (arr[8] as u16) << 8 | (arr[9] as u16),
                    (arr[10] as u16) << 8 | (arr[11] as u16),
                    (arr[12] as u16) << 8 | (arr[13] as u16),
                    (arr[14] as u16) << 8 | (arr[15] as u16),
                );

                #[cfg(windows)]      let sin6_scope_id = *(*sa).u.sin6_scope_id();
                #[cfg(not(windows))] let sin6_scope_id = (*sa).sin6_scope_id;

                Ok(SocketAddr::V6(SocketAddrV6::new(ip,
                                                    ::ntoh((*sa).sin6_port),
                                                    (*sa).sin6_flowinfo,
                                                    sin6_scope_id)))
            }
        }
        _ => Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid argument")),
    }
}
<commit_msg>Remove conditional len_t as socklen_t is now defined for aarch64-linux-android<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt;
use std::io;
use std::mem;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
#[cfg(target_os = "redox")]
use libc::c_int;
#[cfg(unix)]
use libc::c_int;
#[cfg(windows)]
use winapi::ctypes::c_int;

use sys;
use sys::c;

pub struct Socket {
    inner: sys::Socket,
}

impl Socket {
    pub fn new(family: c_int, ty: c_int) -> io::Result<Socket> {
        Ok(Socket { inner: try!(sys::Socket::new(family, ty)) })
    }

    pub fn bind(&self, addr: &SocketAddr) -> io::Result<()> {
        let (addr, len) = addr2raw(addr);
        unsafe {
            ::cvt(c::bind(self.inner.raw(), addr, len as c::socklen_t)).map(|_| ())
        }
    }

    pub fn listen(&self, backlog: i32) -> io::Result<()> {
        unsafe {
            ::cvt(c::listen(self.inner.raw(), backlog)).map(|_| ())
        }
    }

    pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
        let (addr, len) = addr2raw(addr);
        unsafe {
            ::cvt(c::connect(self.inner.raw(), addr, len)).map(|_| ())
        }
    }

    pub fn getsockname(&self) -> io::Result<SocketAddr> {
        unsafe {
            let mut storage: c::sockaddr_storage = mem::zeroed();
            let mut len = mem::size_of_val(&storage) as c::socklen_t;
            try!(::cvt(c::getsockname(self.inner.raw(),
                                      &mut storage as *mut _ as *mut _,
                                      &mut len)));
            raw2addr(&storage, len)
        }
    }
}

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

impl ::AsInner for Socket {
    type Inner = sys::Socket;
    fn as_inner(&self) -> &sys::Socket { &self.inner }
}

impl ::FromInner for Socket {
    type Inner = sys::Socket;
    fn from_inner(sock: sys::Socket) -> Socket {
        Socket { inner: sock }
    }
}

impl ::IntoInner for Socket {
    type Inner = sys::Socket;
    fn into_inner(self) -> sys::Socket { self.inner }
}

fn addr2raw(addr: &SocketAddr) -> (*const c::sockaddr, c::socklen_t) {
    match *addr {
        SocketAddr::V4(ref a) => {
            (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t)
        }
        SocketAddr::V6(ref a) => {
            (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t)
        }
    }
}

fn raw2addr(storage: &c::sockaddr_storage, len: c::socklen_t) -> io::Result<SocketAddr> {
    match storage.ss_family as c_int {
        c::AF_INET => {
            unsafe {
                assert!(len as usize >= mem::size_of::<c::sockaddr_in>());
                let sa = storage as *const _ as *const c::sockaddr_in;
                let bits = c::sockaddr_in_u32(&(*sa));
                let ip = Ipv4Addr::new((bits >> 24) as u8,
                                       (bits >> 16) as u8,
                                       (bits >> 8) as u8,
                                       bits as u8);
                Ok(SocketAddr::V4(SocketAddrV4::new(ip, ::ntoh((*sa).sin_port))))
            }
        }
        c::AF_INET6 => {
            unsafe {
                assert!(len as usize >= mem::size_of::<c::sockaddr_in6>());

                let sa = storage as *const _ as *const c::sockaddr_in6;
                #[cfg(windows)]      let arr = (*sa).sin6_addr.u.Byte();
                #[cfg(not(windows))] let arr = (*sa).sin6_addr.s6_addr;

                let ip = Ipv6Addr::new(
                    (arr[0] as u16) << 8 | (arr[1] as u16),
                    (arr[2] as u16) << 8 | (arr[3] as u16),
                    (arr[4] as u16) << 8 | (arr[5] as u16),
                    (arr[6] as u16) << 8 | (arr[7] as u16),
                    (arr[8] as u16) << 8 | (arr[9] as u16),
                    (arr[10] as u16) << 8 | (arr[11] as u16),
                    (arr[12] as u16) << 8 | (arr[13] as u16),
                    (arr[14] as u16) << 8 | (arr[15] as u16),
                );

                #[cfg(windows)]      let sin6_scope_id = *(*sa).u.sin6_scope_id();
                #[cfg(not(windows))] let sin6_scope_id = (*sa).sin6_scope_id;

                Ok(SocketAddr::V6(SocketAddrV6::new(ip,
                                                    ::ntoh((*sa).sin6_port),
                                                    (*sa).sin6_flowinfo,
                                                    sin6_scope_id)))
            }
        }
        _ => Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid argument")),
    }
}
<|endoftext|>


<commit_before>use traits::*;

pub enum Method {
    RK2,
    RK4,
}

/**
```
use ode::{Method, Solver};

let ini_cond: Vec<f32> = vec![1., 2.];

// simple config
Solver::new(&ini_cond, |t: &f32, _: &Vec<f32>| vec![2.*t])
    .method(Method::RK4)
    .run();

// complex config
let mut s = Solver::new(&ini_cond, |t: &f32, _: &Vec<f32>| vec![2.*t] );
s.method(Method::RK4);

// run the solver
let (times, pos) = s.run();
```
*/
pub struct Solver<T, F>
    where T: Number,
          F: Fn(&T, &Vec<T>) -> Vec<T> {
    method: Method,
    weights: Vec<T>,
    weight_sum: T,
    step: T,
    initial_conditions: Vec<T>,
    function: F,
}

impl<T, F> Solver<T, F>
    where T: Number,
          F: Fn(&T, &Vec<T>) -> Vec<T> {

    /*
    Re-calculate the sum of the registered weights.
    */
    fn sum_weights(weights: &Vec<T>) -> T {
        weights
            .iter()
            .fold(T::zero(), |sum, i| sum + i.clone())
    }

    /**
    Return the default weights for the intermidiate points of a given method.

    Return values are:

    - `Method::RK2`: `vec![T::from(1), T::from(1)],`
    - `Method::RK4`: `vec![T::from(1), T::from(2), T::from(2), T::from(1)],`
    */
    fn get_default_weights_for(method: &Method) -> Vec<T> {
        match method {
            &Method::RK2 => vec![
                T::from_str_radix("1", 10).ok().unwrap(),
                T::from_str_radix("1", 10).ok().unwrap()
            ],

            &Method::RK4 => vec![
                T::from_str_radix("1", 10).ok().unwrap(),
                T::from_str_radix("2", 10).ok().unwrap(),
                T::from_str_radix("2", 10).ok().unwrap(),
                T::from_str_radix("1", 10).ok().unwrap()
            ],
        }
    }

    /**
    Start building a new Solver.

    Default values are:

    - method: `Method::RK4`,
    - intermidiate point weights: `vec![1, 2, 2, 1]`
    - step size: `T::from_str_radix("10e-3", 10)`
    */
    pub fn new(initial_conditions: &Vec<T>, function: F) -> Solver<T, F> {
        let weights = Self::get_default_weights_for(&Method::RK4);
        let sum_of_weights = Self::sum_weights(&weights);
        let default_step = T::from_str_radix("10e-3", 10).ok().unwrap();

        Solver {
            method:             Method::RK4,
            weights:            weights,
            weight_sum:         sum_of_weights,
            step:               default_step,
            initial_conditions: initial_conditions.clone(),
            function:           function,
        }
    }

    /**
    Select the desired algorithm to solve the givem problem, also updating the
    weights based on default values. To manually alter these values, please
    check `Self::change_weight()`.
    */
    pub fn method(&mut self, new_method: Method) -> &mut Solver<T, F> {
        self.weights = Self::get_default_weights_for(&new_method);
        self.method = new_method;
        self.weight_sum = Self::sum_weights(&self.weights);

        self
    }

    /**
    Modify the default weighting applyed to each intermidiate point.
    */
    pub fn change_weight(&mut self, new_weights: Vec<T>) -> &mut Solver<T, F> {
        self.weights = new_weights.clone();
        self.weight_sum = Self::sum_weights(&self.weights);

        self
    }

    /**
    Validates the data passed to the solver.

    This is tipically called by `run()` before attempting to solve the passed
    function, but was made public so the data can be verified and corrected
    without a panic.

    Data checks are:

    - `Self::weights.len()` should match the selected method:

        - `Method::RK2` requires 2 weights;
        - `Method::RK4` requires 4 weights;
    */
    pub fn validate(&self) -> bool {
        self.weights.len() == match self.method {
            Method::RK2 => 2,
            Method::RK4 => 4,
        }
    }

    /**
    Check and run the solver, returning the results of the calculation.

    Notice that, before the solver actually runs, it validates its data by
    calling `Self::validate()` within an `assert!`. See that function for more
    details.
    */
    pub fn run(&self) -> (Vec<T>, Vec<Vec<T>>) {
        assert!(self.validate());

        (Vec::new(), Vec::new())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_works() {
        let _ = Solver::new(&vec![0., 0.],
                            |t: &f32, _: &Vec<f32>| -> Vec<f32> {
                                vec![2.*t]
                            });
    }
}
<commit_msg>Simplify the conversions<commit_after>use traits::*;

pub enum Method {
    RK2,
    RK4,
}

/**
```
use ode::{Method, Solver};

let ini_cond: Vec<f32> = vec![1., 2.];

// simple config
Solver::new(&ini_cond, |t: &f32, _: &Vec<f32>| vec![2.*t])
    .method(Method::RK4)
    .run();

// complex config
let mut s = Solver::new(&ini_cond, |t: &f32, _: &Vec<f32>| vec![2.*t] );
s.method(Method::RK4);

// run the solver
let (times, pos) = s.run();
```
*/
pub struct Solver<T, F>
    where T: Number,
          F: Fn(&T, &Vec<T>) -> Vec<T> {
    method: Method,
    weights: Vec<T>,
    weight_sum: T,
    step: T,
    initial_conditions: Vec<T>,
    function: F,
}

impl<T, F> Solver<T, F>
    where T: Number,
          F: Fn(&T, &Vec<T>) -> Vec<T> {

    /*
    Re-calculate the sum of the registered weights.
    */
    fn sum_weights(weights: &Vec<T>) -> T {
        weights
            .iter()
            .fold(T::zero(), |sum, i| sum + i.clone())
    }

    /**
    Return the default weights for the intermidiate points of a given method.

    Return values are:

    - `Method::RK2`: `vec![1, 1],`
    - `Method::RK4`: `vec![1, 2, 2, 1],`

    (Note that each internal value of the vector will be converted to `T` via
    `T::from_str_radix()`.)
    */
    fn get_default_weights_for(method: &Method) -> Vec<T> {
        let weights = match method {
            &Method::RK2 => vec!["1", "1"],
            &Method::RK4 => vec!["1", "2", "2", "1"],
        };

        weights
            .iter()
            .map(|el| T::from_str_radix(el, 10).ok().unwrap())
            .collect()
    }

    /**
    Start building a new Solver.

    Default values are:

    - method: `Method::RK4`,
    - intermidiate point weights: `vec![1, 2, 2, 1]`
    - step size: `10e-3`

    (Note that these values will be converted to `T` via `T::from_str_radix()`.)
    */
    pub fn new(initial_conditions: &Vec<T>, function: F) -> Solver<T, F> {
        let weights = Self::get_default_weights_for(&Method::RK4);
        let sum_of_weights = Self::sum_weights(&weights);
        let default_step = T::from_str_radix("10e-3", 10).ok().unwrap();

        Solver {
            method:             Method::RK4,
            weights:            weights,
            weight_sum:         sum_of_weights,
            step:               default_step,
            initial_conditions: initial_conditions.clone(),
            function:           function,
        }
    }

    /**
    Select the desired algorithm to solve the givem problem, also updating the
    weights based on default values. To manually alter these values, please
    check `Self::change_weight()`.
    */
    pub fn method(&mut self, new_method: Method) -> &mut Solver<T, F> {
        self.weights = Self::get_default_weights_for(&new_method);
        self.method = new_method;
        self.weight_sum = Self::sum_weights(&self.weights);

        self
    }

    /**
    Modify the default weighting applyed to each intermidiate point.
    */
    pub fn change_weight(&mut self, new_weights: Vec<T>) -> &mut Solver<T, F> {
        self.weights = new_weights.clone();
        self.weight_sum = Self::sum_weights(&self.weights);

        self
    }

    /**
    Validates the data passed to the solver.

    This is tipically called by `run()` before attempting to solve the passed
    function, but was made public so the data can be verified and corrected
    without a panic.

    Data checks are:

    - `Self::weights.len()` should match the selected method:

        - `Method::RK2` requires 2 weights;
        - `Method::RK4` requires 4 weights;
    */
    pub fn validate(&self) -> bool {
        self.weights.len() == match self.method {
            Method::RK2 => 2,
            Method::RK4 => 4,
        }
    }

    /**
    Check and run the solver, returning the results of the calculation.

    Notice that, before the solver actually runs, it validates its data by
    calling `Self::validate()` within an `assert!`. See that function for more
    details.
    */
    pub fn run(&self) -> (Vec<T>, Vec<Vec<T>>) {
        assert!(self.validate());

        (Vec::new(), Vec::new())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_works() {
        let _ = Solver::new(&vec![0., 0.],
                            |t: &f32, _: &Vec<f32>| -> Vec<f32> {
                                vec![2.*t]
                            });
    }
}
<|endoftext|>


<commit_before>use std::convert::Into;
use std::convert::From;

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TaskStatus {
    Pending,
    Deleted,
    Completed,
    Waiting,
    Recurring
}

impl TaskStatus {

    pub fn from_str(s: &str) -> Option<TaskStatus> {
        match s {
            "pending"   => Some(TaskStatus::Pending),
            "deleted"   => Some(TaskStatus::Deleted),
            "completed" => Some(TaskStatus::Completed),
            "waiting"   => Some(TaskStatus::Waiting),
            "recurring" => Some(TaskStatus::Recurring),
            _           => None,
        }
    }

}

impl Into<String> for TaskStatus {

    fn into(self) -> String {
        String::from(match self {
            TaskStatus::Pending   => "pending",
            TaskStatus::Deleted   => "deleted",
            TaskStatus::Completed => "completed",
            TaskStatus::Waiting   => "waiting",
            TaskStatus::Recurring => "recurring",
        })
    }

}

<commit_msg>Impl De/Serialize for Status<commit_after>use serde::Serialize;
use serde::Serializer;
use serde::Deserialize;
use serde::Deserializer;
use serde::de::Error;
use serde::de::Visitor;

use std::convert::Into;
use std::convert::From;

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TaskStatus {
    Pending,
    Deleted,
    Completed,
    Waiting,
    Recurring
}

impl Serialize for TaskStatus {

    fn serialize<S>(&self, serializer: &mut S) -> Result<(), Error>
        where S: Serializer
    {
        serializer.serialize_str(
            match self {
                TaskStatus::Pending   => "pending",
                TaskStatus::Deleted   => "deleted",
                TaskStatus::Completed => "completed",
                TaskStatus::Waiting   => "waiting",
                TaskStatus::Recurring => "recurring",
            }
        )
    }

}

impl Deserialize for TaskStatus {
    fn deserialize<D>(deserializer: &mut D) -> Result<TaskStatus, Error>
        where D: Deserializer
    {
        struct TaskStatusVisitor;

        impl Visitor for TaskStatusVisitor {
            type Value = TaskStatus;

            fn visit_str<E>(&mut self, value: &str) -> Result<TaskStatus, E>
                where E: Error
            {
                match value {
                    "pending"   => Ok(TaskStatus::Pending),
                    "deleted"   => Ok(TaskStatus::Deleted),
                    "completed" => Ok(TaskStatus::Completed),
                    "waiting"   => Ok(TaskStatus::Waiting),
                    "recurring" => Ok(TaskStatus::Recurrin),
                    _           => Err(Error::custom("expected one of pending, deleted, completed, waiting, recurring")),
                }
            }
        }

        deserializer.deserialize(TaskStatusVisitor)
    }
}

<|endoftext|>