<commit_before>#![doc(html_root_url = "https://docs.rs/ipnet/1.0.0")]
//! Types for IPv4 and IPv6 network addresses.
//!
//! This module provides types and useful methods for working with IPv4
//! and IPv6 network addresses, commonly called IP prefixes. The new
//! [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`] types build on the existing
//! [`IpAddr`], [`Ipv4Addr`], and [`Ipv6Addr`] types already provided in
//! Rust's standard library and align to their design to stay
//! consistent.
//!
//! The module also provides types for iterating over IP address ranges,
//! and useful traits that extend [`Ipv4Addr`] and [`Ipv6Addr`] with
//! methods for addition, subtraction, bitwise-and, and bitwise-or
//! operations that are missing in Rust's standard library.
//!
//! The module only uses stable features so it is guaranteed to compile
//! using the stable toolchain.
//!
//! # Organization
//!
//! * [`IpNet`] represents an IP network address, either IPv4 or IPv6.
//! * [`Ipv4Net`] and [`Ipv6Net`] are respectively IPv4 and IPv6 network
//!   addresses.
//! * [`IpSubnets`], [`Ipv4Subnets`], and [`Ipv6Subnets`] are iterators
//!   that generate the smallest set of IP network addresses bound by an
//!   IP address range and minimum prefix length. These are returned by
//!   the [`subnets()`] methods and used in the [`aggregate()`] methods.
//! * [`IpAddrRange`], [`Ipv4AddrRange`], and [`Ipv6AddrRange`] provide
//!   iteration over ranges of IP addresses. These are returned by the
//!   [`hosts()`] methods.
//! * The [`IpAdd`], [`IpSub`], [`IpBitAnd`], [`IpBitOr`] traits extend
//!   the [`Ipv4Addr`] and [`Ipv6Addr`] types with methods to perform
//!   these operations.
//! * [`Emu128`] is an emulated 128 bit unsigned integer implemented in
//!   this module using a struct of two `u64` types. This is useful for
//!   operations on IPv6 address, which are 128 bit unsigned integers.
//!
//! [`IpNet`]: enum.IpNet.html
//! [`Ipv4Net`]: struct.Ipv4Net.html
//! [`Ipv6Net`]: struct.Ipv6Net.html
//! [`IpAddr`]: https://doc.rust-lang.org/std/net/enum.IpAddr.html
//! [`Ipv4Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html
//! [`Ipv6Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html
//! [`IpSubnets`]: enum.IpSubnets.html
//! [`Ipv4Subnets`]: struct.Ipv4Subnets.html
//! [`Ipv6Subnets`]: struct.Ipv6Subnets.html
//! [`subnets()`]: enum.IpNet.html#method.subnets
//! [`aggregate()`]: enum.IpNet.html#method.aggregate
//! [`IpAddrRange`]: enum.IpAddrIter.html
//! [`Ipv4AddrRange`]: struct.Ipv4AddrIter.html
//! [`Ipv6AddrRange`]: struct.Ipv6AddrIter.html
//! [`hosts()`]: enum.IpNet.html#method.hosts
//! [`IpAdd`]: trait.IpAdd.html
//! [`IpSub`]: trait.IpSub.html
//! [`IpBitAnd`]: trait.IpBitAnd.html
//! [`IpBitOr`]: trait.IpBitOr.html
//! [`Emu128`]: struct.Emu128.html
//!
//! # Serde support
//!
//! This library comes with support for [serde](https://serde.rs) but it's
//! not enabled by default. Use the `with-serde` [feature] to enable.
//!
//! [feature]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section

#[cfg(feature = "with-serde")]
extern crate serde;
#[cfg(feature = "with-serde")]
#[macro_use]
extern crate serde_derive;

pub use self::emu128::Emu128;
pub use self::ipext::{IpAdd, IpSub, IpBitAnd, IpBitOr, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange};
pub use self::ipnet::{IpNet, Ipv4Net, Ipv6Net, Contains, PrefixLenError, IpSubnets, Ipv4Subnets, Ipv6Subnets};
pub use self::parser::AddrParseError;

mod emu128;
mod ipext;
mod ipnet;
mod parser;
#[cfg(feature = "with-serde")]
mod with_serde;
<commit_msg>Fix broken links in documentation<commit_after>#![doc(html_root_url = "https://docs.rs/ipnet/1.0.0")]
//! Types for IPv4 and IPv6 network addresses.
//!
//! This module provides types and useful methods for working with IPv4
//! and IPv6 network addresses, commonly called IP prefixes. The new
//! [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`] types build on the existing
//! [`IpAddr`], [`Ipv4Addr`], and [`Ipv6Addr`] types already provided in
//! Rust's standard library and align to their design to stay
//! consistent.
//!
//! The module also provides types for iterating over IP address ranges,
//! and useful traits that extend [`Ipv4Addr`] and [`Ipv6Addr`] with
//! methods for addition, subtraction, bitwise-and, and bitwise-or
//! operations that are missing in Rust's standard library.
//!
//! The module only uses stable features so it is guaranteed to compile
//! using the stable toolchain.
//!
//! # Organization
//!
//! * [`IpNet`] represents an IP network address, either IPv4 or IPv6.
//! * [`Ipv4Net`] and [`Ipv6Net`] are respectively IPv4 and IPv6 network
//!   addresses.
//! * [`IpSubnets`], [`Ipv4Subnets`], and [`Ipv6Subnets`] are iterators
//!   that generate the smallest set of IP network addresses bound by an
//!   IP address range and minimum prefix length. These are returned by
//!   the [`subnets()`] methods and used in the [`aggregate()`] methods.
//! * [`IpAddrRange`], [`Ipv4AddrRange`], and [`Ipv6AddrRange`] provide
//!   iteration over ranges of IP addresses. These are returned by the
//!   [`hosts()`] methods.
//! * The [`IpAdd`], [`IpSub`], [`IpBitAnd`], [`IpBitOr`] traits extend
//!   the [`Ipv4Addr`] and [`Ipv6Addr`] types with methods to perform
//!   these operations.
//! * [`Emu128`] is an emulated 128 bit unsigned integer implemented in
//!   this module using a struct of two `u64` types. This is useful for
//!   operations on IPv6 address, which are 128 bit unsigned integers.
//!
//! [`IpNet`]: enum.IpNet.html
//! [`Ipv4Net`]: struct.Ipv4Net.html
//! [`Ipv6Net`]: struct.Ipv6Net.html
//! [`IpAddr`]: https://doc.rust-lang.org/std/net/enum.IpAddr.html
//! [`Ipv4Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html
//! [`Ipv6Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html
//! [`IpSubnets`]: enum.IpSubnets.html
//! [`Ipv4Subnets`]: struct.Ipv4Subnets.html
//! [`Ipv6Subnets`]: struct.Ipv6Subnets.html
//! [`subnets()`]: enum.IpNet.html#method.subnets
//! [`aggregate()`]: enum.IpNet.html#method.aggregate
//! [`IpAddrRange`]: enum.IpAddrRange.html
//! [`Ipv4AddrRange`]: struct.Ipv4AddrRange.html
//! [`Ipv6AddrRange`]: struct.Ipv6AddrRange.html
//! [`hosts()`]: enum.IpNet.html#method.hosts
//! [`IpAdd`]: trait.IpAdd.html
//! [`IpSub`]: trait.IpSub.html
//! [`IpBitAnd`]: trait.IpBitAnd.html
//! [`IpBitOr`]: trait.IpBitOr.html
//! [`Emu128`]: struct.Emu128.html
//!
//! # Serde support
//!
//! This library comes with support for [serde](https://serde.rs) but it's
//! not enabled by default. Use the `with-serde` [feature] to enable.
//!
//! [feature]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section

#[cfg(feature = "with-serde")]
extern crate serde;
#[cfg(feature = "with-serde")]
#[macro_use]
extern crate serde_derive;

pub use self::emu128::Emu128;
pub use self::ipext::{IpAdd, IpSub, IpBitAnd, IpBitOr, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange};
pub use self::ipnet::{IpNet, Ipv4Net, Ipv6Net, Contains, PrefixLenError, IpSubnets, Ipv4Subnets, Ipv6Subnets};
pub use self::parser::AddrParseError;

mod emu128;
mod ipext;
mod ipnet;
mod parser;
#[cfg(feature = "with-serde")]
mod with_serde;
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
#![feature(macro_rules)]

pub mod mat;

pub mod vector;
pub mod matrix_vector;
pub mod matrix;

pub mod attribute;
mod default;
mod pointer;
mod scalar;
<commit_msg>Re-export Vector and Matrix traits<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
#![feature(macro_rules)]

pub use vector::Vector;
pub use matrix::Matrix;

pub mod mat;

pub mod vector;
pub mod matrix_vector;
pub mod matrix;

pub mod attribute;
mod default;
mod pointer;
mod scalar;
<|endoftext|>


<commit_before>#![cfg(feature = "tensorflow_unstable")]

extern crate libc;
extern crate libtensorflow_sys;

use std::ffi::CStr;
use std::ffi::CString;
use std::ffi::NulError;
use std::fmt;
use std::fmt::Debug;
use std::fmt::Display;
use std::fmt::Formatter;
use std::ops::Drop;

use libtensorflow_sys as tf;

mod buffer;
pub use buffer::Buffer;

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

fn check_not_null<T>(p: *mut T) -> *mut T {
  assert!(!p.is_null());
  p
}

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

macro_rules! impl_new {
  ($name: ident, $call:ident) => {
    impl $name {
      pub fn new() -> Self {
        unsafe {
          $name {
            inner: check_not_null(tf::$call()),
          }
        }
      }
    }
  }
}

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

macro_rules! impl_drop {
  ($name: ident, $call:ident) => {
    impl Drop for $name {
      fn drop(&mut self) {
        unsafe {
          tf::$call(self.inner);
        }
      }
    }
  }
}

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

macro_rules! c_enum {
  ($enum_name:ident { $($name:ident = $num:expr),* }) => {
    #[derive(PartialEq,Eq,PartialOrd,Ord,Debug)]
    pub enum $enum_name {
      UnrecognizedEnumValue(::libc::c_uint),
      $($name),*
    }

    impl $enum_name {
      #[allow(dead_code)]
      fn from_int(value: ::libc::c_uint) -> $enum_name {
        match value {
          $($num => $enum_name::$name,)*
          c => $enum_name::UnrecognizedEnumValue(c),
        }
      }

      #[allow(dead_code)]
      fn to_int(&self) -> ::libc::c_uint {
        match self {
          &$enum_name::UnrecognizedEnumValue(c) => c,
          $(&$enum_name::$name => $num),*
        }
      }
    }

    impl ::std::fmt::Display for $enum_name {
      fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match self {
          $(&$enum_name::$name => f.write_str(stringify!($name)),)*
          &$enum_name::UnrecognizedEnumValue(c) => write!(f, "UnrecognizedEnumValue({})", c),
        }
      }
    }
  };
  ($enum_name:ident { $($name:ident = $num:expr,)* }) => {
    c_enum!($enum_name { $($name = $num),* });
  }
}

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

c_enum!(Code {
  Ok = 0,
  Cancelled = 1,
  Unknown = 2,
  InvalidArgument = 3,
  DeadlineExceeded = 4,
  NotFound = 5,
  AlreadyExists = 6,
  PermissionDenied = 7,
  ResourceExhausted = 8,
  FailedPrecondition = 9,
  Aborted = 10,
  OutOfRange = 11,
  Unimplemented = 12,
  Internal = 13,
  Unavailable = 14,
  DataLoss = 15,
  Unauthenticated = 16,
});

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

c_enum!(DataType {
  Float = 1,
  Double = 2,
  Int32 = 3,
  UInt8 = 4,
  Int16 = 5,
  Int8 = 6,
  String = 7,
  Complex = 8,
  Int64 = 9,
  Bool = 10,
  QInt8 = 11,
  QUInt8 = 12,
  QInt32 = 13,
  BFloat16 = 14,
  QInt16 = 15,
  QUInt16 = 16,
});

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

pub struct Status {
  inner: *mut tf::TF_Status,
}

impl_new!(Status, TF_NewStatus);
impl_drop!(Status, TF_DeleteStatus);

impl Status {
  pub fn code(&self) -> Code {
    unsafe {
      Code::from_int(tf::TF_GetCode(self.inner))
    }
  }

  pub fn is_ok(&self) -> bool {
    self.code() == Code::Ok
  }
}

impl Display for Status {
  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    unsafe {
      try!(write!(f, "{}: ", self.code()));
      let msg = match CStr::from_ptr(tf::TF_Message(self.inner)).to_str() {
        Ok(s) => s,
        Err(_) => "<invalid UTF-8 in message>",
      };
      f.write_str(msg)
    }
  }
}

impl Debug for Status {
  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    unsafe {
      try!(write!(f, "{{inner:{:?}, ", self.inner));
      try!(write!(f, "{}: ", self.code()));
      let msg = match CStr::from_ptr(tf::TF_Message(self.inner)).to_str() {
        Ok(s) => s,
        Err(_) => "<invalid UTF-8 in message>",
      };
      try!(f.write_str(msg));
      try!(write!(f, "}}"));
      Ok(())
    }
  }
}

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

pub struct SessionOptions {
  inner: *mut tf::TF_SessionOptions,
}

impl SessionOptions {
  pub fn set_target(&mut self, target: &str) -> std::result::Result<(), NulError> {
    let cstr = try!(CString::new(target));
    unsafe {
      tf::TF_SetTarget(self.inner, cstr.as_ptr());
    }
    Ok(())
  }

  pub fn set_config(&mut self, config: &[u8]) -> Result<()> {
    let status = Status::new();
    unsafe {
      tf::TF_SetConfig(self.inner, config.as_ptr() as *const libc::c_void, config.len(), status.inner);
    }
    if status.is_ok() {
      Ok(())
    } else {
      Err(status)
    }
  }
}

impl_new!(SessionOptions, TF_NewSessionOptions);
impl_drop!(SessionOptions, TF_DeleteSessionOptions);

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

pub struct Session {
  inner: *mut tf::TF_Session,
}

impl Session {
  pub fn new(options: &SessionOptions) -> Result<Self> {
    let status = Status::new();
    let inner = unsafe { tf::TF_NewSession(options.inner, status.inner) };
    if inner.is_null() {
      Err(status)
    } else {
      Ok(Session {
        inner: inner,
      })
    }
  }

  pub fn close(&mut self) -> Status {
    let status = Status::new();
    unsafe {
      tf::TF_CloseSession(self.inner, status.inner);
    }
    status
  }

  pub fn extend_graph(&mut self, proto: &[u8]) -> Status {
    let status = Status::new();
    unsafe {
      tf::TF_ExtendGraph(self.inner, proto.as_ptr() as *const libc::c_void, proto.len(), status.inner);
    }
    status
  }
}

impl Drop for Session {
  fn drop(&mut self) {
    let status = Status::new();
    unsafe {
      tf::TF_DeleteSession(self.inner, status.inner);
    }
    // TODO: What do we do with the status?
  }
}

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

pub type Result<T> = std::result::Result<T, Status>;

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

trait TensorType: Default + Clone {
  // TODO: Use associated constants when/if available
  fn data_type() -> DataType;
}

macro_rules! tensor_type {
  ($rust_type:ident, $tensor_type:ident) => {
    impl TensorType for $rust_type {
      fn data_type() -> DataType {
        DataType::$tensor_type
      }
    }
  }
}

tensor_type!(f32, Float);
tensor_type!(f64, Double);
tensor_type!(i32, Int32);
tensor_type!(u8, UInt8);
tensor_type!(i16, Int16);
tensor_type!(i8, Int8);
// TODO: provide type for String
// TODO: provide type for Complex
tensor_type!(i64, Int64);
tensor_type!(bool, Bool);
// TODO: provide type for QInt8
// TODO: provide type for QUInt8
// TODO: provide type for QInt32
// TODO: provide type for BFloat16
// TODO: provide type for QInt16
// TODO: provide type for QUInt16

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

pub struct Tensor<T> {
  inner: *mut tf::TF_Tensor,
  data: Buffer<T>,
  dims: Vec<u64>,
}

extern "C" fn noop_deallocator(_data: *mut ::libc::c_void,
                               _len: ::libc::size_t,
                               _arg: *mut ::libc::c_void)-> () {
}

// TODO: Replace with Iterator::product once that's stable
fn product(values: &[u64]) -> u64 {
  let mut product = 1;
  for v in values.iter() {
    product *= *v;
  }
  product
}

impl<T: TensorType> Tensor<T> {
  pub fn new(dims: &[u64]) -> Self {
    let total = product(dims);
    let data = <Buffer<T>>::new(total as usize);
    // Guaranteed safe to unwrap, because the only way for it to fail is for the
    // length of the buffer not to match the dimensions, and we created it with
    // exactly the right size.
    Self::new_with_buffer(dims, data).unwrap()
  }

  pub fn new_with_buffer(dims: &[u64], data: Buffer<T>) -> Option<Self> {
    let total = product(dims);
    if total != data.len() as u64 {
      return None
    }
    let inner = unsafe {
      tf::TF_NewTensor(T::data_type().to_int(),
                       dims.as_ptr() as *mut i64,
                       dims.len() as i32,
                       data.as_ptr() as *mut libc::c_void,
                       data.len(),
                       Some(noop_deallocator),
                       std::ptr::null_mut())
    };
    let mut dims_vec = Vec::new();
    // TODO: Use extend_from_slice once we're on Rust 1.6
    dims_vec.extend(dims.iter());
    Some(Tensor {
      inner: inner,
      data: data,
      dims: dims_vec,
    })
  }

  pub fn data(&self) -> &Buffer<T> {
    &self.data
  }

  pub fn data_mut(&mut self) -> &mut Buffer<T> {
    &mut self.data
  }

  pub fn dims(&self) -> &[u64] {
    &self.dims
  }
}

impl<T> Drop for Tensor<T> {
  fn drop(&mut self) {
    unsafe {
      tf::TF_DeleteTensor(self.inner);
    }
  }
}

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

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

  fn create_session() -> Session {
    let options = SessionOptions::new();
    match Session::new(&options) {
      Ok(session) => session,
      Err(status) => panic!("Creating session failed with status: {}", status),
    }
  }

  #[test]
  fn smoke() {
    create_session();
  }

  #[test]
  fn test_close() {
    let status = create_session().close();
    assert!(status.is_ok());
  }

  #[test]
  fn test_tensor() {
    let mut tensor = <Tensor<f32>>::new(&[2, 3]);
    assert_eq!(tensor.data().len(), 6);
    tensor.data_mut()[0] = 1.0;
  }

  #[test]
  fn test_set_target() {
    let mut options = SessionOptions::new();
    options.set_target("local").unwrap();
  }

  #[test]
  fn test_set_config() {
    let mut options = SessionOptions::new();
    // An empty array is a valid proto, since all fields are optional.
    options.set_config(&vec![]).unwrap();
  }

  #[test]
  fn test_extend_graph() {
    let mut session = create_session();
    // An empty array is a valid proto, since all fields are optional.
    let status = session.extend_graph(&vec![]);
    assert!(status.is_ok());
  }
}
<commit_msg>Add Status::set and Status::new_set<commit_after>#![cfg(feature = "tensorflow_unstable")]

extern crate libc;
extern crate libtensorflow_sys;

use std::ffi::CStr;
use std::ffi::CString;
use std::ffi::NulError;
use std::fmt;
use std::fmt::Debug;
use std::fmt::Display;
use std::fmt::Formatter;
use std::ops::Drop;

use libtensorflow_sys as tf;

mod buffer;
pub use buffer::Buffer;

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

fn check_not_null<T>(p: *mut T) -> *mut T {
  assert!(!p.is_null());
  p
}

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

macro_rules! impl_new {
  ($name: ident, $call:ident) => {
    impl $name {
      pub fn new() -> Self {
        unsafe {
          $name {
            inner: check_not_null(tf::$call()),
          }
        }
      }
    }
  }
}

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

macro_rules! impl_drop {
  ($name: ident, $call:ident) => {
    impl Drop for $name {
      fn drop(&mut self) {
        unsafe {
          tf::$call(self.inner);
        }
      }
    }
  }
}

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

macro_rules! c_enum {
  ($enum_name:ident { $($name:ident = $num:expr),* }) => {
    #[derive(PartialEq,Eq,PartialOrd,Ord,Debug)]
    pub enum $enum_name {
      UnrecognizedEnumValue(::libc::c_uint),
      $($name),*
    }

    impl $enum_name {
      #[allow(dead_code)]
      fn from_int(value: ::libc::c_uint) -> $enum_name {
        match value {
          $($num => $enum_name::$name,)*
          c => $enum_name::UnrecognizedEnumValue(c),
        }
      }

      #[allow(dead_code)]
      fn to_int(&self) -> ::libc::c_uint {
        match self {
          &$enum_name::UnrecognizedEnumValue(c) => c,
          $(&$enum_name::$name => $num),*
        }
      }
    }

    impl ::std::fmt::Display for $enum_name {
      fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match self {
          $(&$enum_name::$name => f.write_str(stringify!($name)),)*
          &$enum_name::UnrecognizedEnumValue(c) => write!(f, "UnrecognizedEnumValue({})", c),
        }
      }
    }
  };
  ($enum_name:ident { $($name:ident = $num:expr,)* }) => {
    c_enum!($enum_name { $($name = $num),* });
  }
}

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

c_enum!(Code {
  Ok = 0,
  Cancelled = 1,
  Unknown = 2,
  InvalidArgument = 3,
  DeadlineExceeded = 4,
  NotFound = 5,
  AlreadyExists = 6,
  PermissionDenied = 7,
  ResourceExhausted = 8,
  FailedPrecondition = 9,
  Aborted = 10,
  OutOfRange = 11,
  Unimplemented = 12,
  Internal = 13,
  Unavailable = 14,
  DataLoss = 15,
  Unauthenticated = 16,
});

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

c_enum!(DataType {
  Float = 1,
  Double = 2,
  Int32 = 3,
  UInt8 = 4,
  Int16 = 5,
  Int8 = 6,
  String = 7,
  Complex = 8,
  Int64 = 9,
  Bool = 10,
  QInt8 = 11,
  QUInt8 = 12,
  QInt32 = 13,
  BFloat16 = 14,
  QInt16 = 15,
  QUInt16 = 16,
});

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

pub struct Status {
  inner: *mut tf::TF_Status,
}

impl_new!(Status, TF_NewStatus);
impl_drop!(Status, TF_DeleteStatus);

impl Status {
  pub fn new_set(code: Code, msg: &str) -> std::result::Result<Status, NulError> {
    let status = Status::new();
    try!(status.set(code, msg));
    Ok(status)
  }

  pub fn code(&self) -> Code {
    unsafe {
      Code::from_int(tf::TF_GetCode(self.inner))
    }
  }

  pub fn is_ok(&self) -> bool {
    self.code() == Code::Ok
  }

  pub fn set(&mut self, code: Code, msg: &str) -> std::result::Result<(), NulError> {
    let message = try!(CString::new(msg)).as_ptr();
    unsafe {
      tf::TF_SetStatus(self.inner, code.to_int(), message);
    }
    Ok(())
  }
}

impl Display for Status {
  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    unsafe {
      try!(write!(f, "{}: ", self.code()));
      let msg = match CStr::from_ptr(tf::TF_Message(self.inner)).to_str() {
        Ok(s) => s,
        Err(_) => "<invalid UTF-8 in message>",
      };
      f.write_str(msg)
    }
  }
}

impl Debug for Status {
  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    unsafe {
      try!(write!(f, "{{inner:{:?}, ", self.inner));
      try!(write!(f, "{}: ", self.code()));
      let msg = match CStr::from_ptr(tf::TF_Message(self.inner)).to_str() {
        Ok(s) => s,
        Err(_) => "<invalid UTF-8 in message>",
      };
      try!(f.write_str(msg));
      try!(write!(f, "}}"));
      Ok(())
    }
  }
}

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

pub struct SessionOptions {
  inner: *mut tf::TF_SessionOptions,
}

impl SessionOptions {
  pub fn set_target(&mut self, target: &str) -> std::result::Result<(), NulError> {
    let cstr = try!(CString::new(target));
    unsafe {
      tf::TF_SetTarget(self.inner, cstr.as_ptr());
    }
    Ok(())
  }

  pub fn set_config(&mut self, config: &[u8]) -> Result<()> {
    let status = Status::new();
    unsafe {
      tf::TF_SetConfig(self.inner, config.as_ptr() as *const libc::c_void, config.len(), status.inner);
    }
    if status.is_ok() {
      Ok(())
    } else {
      Err(status)
    }
  }
}

impl_new!(SessionOptions, TF_NewSessionOptions);
impl_drop!(SessionOptions, TF_DeleteSessionOptions);

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

pub struct Session {
  inner: *mut tf::TF_Session,
}

impl Session {
  pub fn new(options: &SessionOptions) -> Result<Self> {
    let status = Status::new();
    let inner = unsafe { tf::TF_NewSession(options.inner, status.inner) };
    if inner.is_null() {
      Err(status)
    } else {
      Ok(Session {
        inner: inner,
      })
    }
  }

  pub fn close(&mut self) -> Status {
    let status = Status::new();
    unsafe {
      tf::TF_CloseSession(self.inner, status.inner);
    }
    status
  }

  pub fn extend_graph(&mut self, proto: &[u8]) -> Status {
    let status = Status::new();
    unsafe {
      tf::TF_ExtendGraph(self.inner, proto.as_ptr() as *const libc::c_void, proto.len(), status.inner);
    }
    status
  }
}

impl Drop for Session {
  fn drop(&mut self) {
    let status = Status::new();
    unsafe {
      tf::TF_DeleteSession(self.inner, status.inner);
    }
    // TODO: What do we do with the status?
  }
}

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

pub type Result<T> = std::result::Result<T, Status>;

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

trait TensorType: Default + Clone {
  // TODO: Use associated constants when/if available
  fn data_type() -> DataType;
}

macro_rules! tensor_type {
  ($rust_type:ident, $tensor_type:ident) => {
    impl TensorType for $rust_type {
      fn data_type() -> DataType {
        DataType::$tensor_type
      }
    }
  }
}

tensor_type!(f32, Float);
tensor_type!(f64, Double);
tensor_type!(i32, Int32);
tensor_type!(u8, UInt8);
tensor_type!(i16, Int16);
tensor_type!(i8, Int8);
// TODO: provide type for String
// TODO: provide type for Complex
tensor_type!(i64, Int64);
tensor_type!(bool, Bool);
// TODO: provide type for QInt8
// TODO: provide type for QUInt8
// TODO: provide type for QInt32
// TODO: provide type for BFloat16
// TODO: provide type for QInt16
// TODO: provide type for QUInt16

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

pub struct Tensor<T> {
  inner: *mut tf::TF_Tensor,
  data: Buffer<T>,
  dims: Vec<u64>,
}

extern "C" fn noop_deallocator(_data: *mut ::libc::c_void,
                               _len: ::libc::size_t,
                               _arg: *mut ::libc::c_void)-> () {
}

// TODO: Replace with Iterator::product once that's stable
fn product(values: &[u64]) -> u64 {
  let mut product = 1;
  for v in values.iter() {
    product *= *v;
  }
  product
}

impl<T: TensorType> Tensor<T> {
  pub fn new(dims: &[u64]) -> Self {
    let total = product(dims);
    let data = <Buffer<T>>::new(total as usize);
    // Guaranteed safe to unwrap, because the only way for it to fail is for the
    // length of the buffer not to match the dimensions, and we created it with
    // exactly the right size.
    Self::new_with_buffer(dims, data).unwrap()
  }

  pub fn new_with_buffer(dims: &[u64], data: Buffer<T>) -> Option<Self> {
    let total = product(dims);
    if total != data.len() as u64 {
      return None
    }
    let inner = unsafe {
      tf::TF_NewTensor(T::data_type().to_int(),
                       dims.as_ptr() as *mut i64,
                       dims.len() as i32,
                       data.as_ptr() as *mut libc::c_void,
                       data.len(),
                       Some(noop_deallocator),
                       std::ptr::null_mut())
    };
    let mut dims_vec = Vec::new();
    // TODO: Use extend_from_slice once we're on Rust 1.6
    dims_vec.extend(dims.iter());
    Some(Tensor {
      inner: inner,
      data: data,
      dims: dims_vec,
    })
  }

  pub fn data(&self) -> &Buffer<T> {
    &self.data
  }

  pub fn data_mut(&mut self) -> &mut Buffer<T> {
    &mut self.data
  }

  pub fn dims(&self) -> &[u64] {
    &self.dims
  }
}

impl<T> Drop for Tensor<T> {
  fn drop(&mut self) {
    unsafe {
      tf::TF_DeleteTensor(self.inner);
    }
  }
}

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

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

  fn create_session() -> Session {
    let options = SessionOptions::new();
    match Session::new(&options) {
      Ok(session) => session,
      Err(status) => panic!("Creating session failed with status: {}", status),
    }
  }

  #[test]
  fn smoke() {
    create_session();
  }

  #[test]
  fn test_close() {
    let status = create_session().close();
    assert!(status.is_ok());
  }

  #[test]
  fn test_tensor() {
    let mut tensor = <Tensor<f32>>::new(&[2, 3]);
    assert_eq!(tensor.data().len(), 6);
    tensor.data_mut()[0] = 1.0;
  }

  #[test]
  fn test_set_target() {
    let mut options = SessionOptions::new();
    options.set_target("local").unwrap();
  }

  #[test]
  fn test_set_config() {
    let mut options = SessionOptions::new();
    // An empty array is a valid proto, since all fields are optional.
    options.set_config(&vec![]).unwrap();
  }

  #[test]
  fn test_extend_graph() {
    let mut session = create_session();
    // An empty array is a valid proto, since all fields are optional.
    let status = session.extend_graph(&vec![]);
    assert!(status.is_ok());
  }
}
<|endoftext|>


<commit_before>extern crate libc;

use std::os::raw;
use std::ffi::CString;
use std::mem::transmute;

#[link(name = "rust")]
extern {
  fn klee_make_symbolic(data: *const raw::c_void, length: libc::size_t, name: *const raw::c_char);
}

pub fn any(data: *const raw::c_void, length: usize, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(data, length as libc::size_t, name_cstr.as_ptr());
  }
}

pub fn i32(data: *const i32, name: &str) {
  any(transmute(data), 4, name);
}

pub fn u32(data: *const u32, name: &str) {
  any(transmute(data), 4, name);
}

pub fn str(data: &str, name: &str) {
  any(transmute(data), data.len(), name);
}
<commit_msg>Update lib.rs<commit_after>extern crate libc;

use std::os::raw;
use std::ffi::CString;
use std::mem::transmute;

#[link(name = "rust")]
extern {
  fn klee_make_symbolic(data: *const raw::c_void, length: libc::size_t, name: *const raw::c_char);
}

pub fn any(data: *const raw::c_void, length: usize, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(data, length as libc::size_t, name_cstr.as_ptr());
  }
}

pub fn i32(data: *const i32, name: &str) {
  unsafe { any(transmute(data), 4, name); }
}

pub fn u32(data: *const u32, name: &str) {
  unsafe { any(transmute(data), 4, name); }
}

pub fn str(data: &str, name: &str) {
  unsafe { any(transmute(data), data.len(), name); }
}
<|endoftext|>


<commit_before>
#![warn(missing_docs)]

//! This crate provides types `Nil` and `Cons<H, T>`, which together allow for creating lists consisting of multiple types.
//! The types in the list are present in the type of the list, so that `Cons<i32, Cons<i64, Nil>>` contains an `i32` and an `i64`.
//! If type `T` is present exactly once in an `HList`, it is usually possible to allow the compiler to find the `T` in the `HList` by using the `Find` trait.

/// The empty `HList`.
pub struct Nil;

/// An `HList` with `H` at position 0, and `T` as the rest of the list.
pub struct Cons<H, T>(pub H, pub T);

/// A marker trait that `Nil` and `Cons<H, T>` satisfies.
/// Not currently used to enforce proper hlists, although this may change.
/// Provides the `push()` method
pub trait HList: Sized {
    /// Consumes the `HList`, and returns a new HList with `item` at the beginning.
    fn push<N>(self, item: N) -> Cons<N, Self> {
        Cons(item, self)
    }
}

impl HList for Nil {}
impl<H, T> HList for Cons<H, T> {}

/// Used as an index into an `HList`.
///
/// `Here` is 0, pointing to the head of the HList.
///
/// Users should normally allow type inference to create this type
#[allow(dead_code)]
pub enum Here {}

/// Used as an index into an `HList`.
///
/// `There<T>` is 1 + `T`.
///
/// Users should normally allow type inference to create this type.
#[allow(dead_code)]
pub struct There<T>(std::marker::PhantomData<T>);

/// `Find<T, I>` is implemented for an `HList` if index `I` of the `HList` is a `T`
///
/// Rust's type inferencer can often produce a correct `I`
/// if there is exactly one `T` in the `HList`.
///
/// ```rust
/// use hlist::{HList, Nil, Find};
///
/// // The type of list is Cons<i64, Cons<i32, Nil>>
/// let list = Nil.push(0i32).push(1i64);
///
/// // Here list satisfies the trait Find<i64, Here>.
/// // The compiler infers the second type parameter.
/// let a: i64 = *list.get();
/// assert!(a == 1);
///
/// // Here list satisfies the trait Find<i32, There<Here>>.
/// let b: i32 = *list.get();
/// assert!(b == 0);
/// ```
///
/// Functions that need to look up values of a type in an HList given to them should get the index from the call site:
///
/// ```rust
/// fn foo<I, L: Find<i32, I>>(list: &L) -> i32 {
///     *list.get()
/// }
/// let list = Nil.push("foo").push(5i32).push("bar");
/// assert!(foo(&list) == 5);
/// ```
///
/// When `foo()` is called, the compiler figures out the appropriate value for `I`.
pub trait Find<T, I> {
    /// Retrieves a &T.
    /// Allows for type inferencing to act like type-directed search
    /// ```rust
    /// use hlist::{HList, Nil, Find}
    ///
    /// let list = Nil.push(0i32).push(1i64);
    /// let a: i64 = *list.get();
    /// assert!(a == 1);
    fn get(&self) -> &T;

    /// Retrieves a &mut T.
    /// Allows for type inferencing to act like type-directed search
    /// ```rust
    /// use hlist::{HList, Nil, Find}
    ///
    /// let mut list = Nil.push(0i32).push(1i64);
    /// *list.get_mut() = 5i32;
    /// let a: i32 = *list.get()
    /// assert!(a == 5);
    fn get_mut(&mut self) -> &mut T;
}

impl<T, Tail> Find<T, Here> for Cons<T, Tail> {
    fn get(&self) -> &T {
        &self.0
    }
    fn get_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<Head, T, Tail, TailIndex> Find<T, There<TailIndex>> for Cons<Head, Tail>
    where Tail: Find<T, TailIndex> {
    fn get(&self) -> &T {
        self.1.get()
    }
    fn get_mut(&mut self) -> &mut T {
        self.1.get_mut()
    }
}

#[test]
fn test_get() {
    let list = Nil.push(5i32).push("Foo");
    let a: i32 = *list.get();
    let b: &str = *list.get();
    assert!(a == 5i32);
    assert!(b == "Foo");
}

#[test]
fn test_get_mut() {
    let mut list = Nil.push(5i32).push("Foo");
    *list.get_mut() = 6i32;
    *list.get_mut() = "Bar";
    let a: i32 = *list.get();
    let b: &str = *list.get();
    assert!(a == 6i32);
    assert!(b == "Bar");
}

#[test]
fn test_index_as_type_parameter() {
    fn foo<I, L: Find<i32, I>>(list: &L) -> i32 {
        *list.get()
    }
    let list = Nil.push("foo").push(5i32).push("bar");
    assert!(foo(&list) == 5);
}
<commit_msg>Fix some formatting<commit_after>
#![warn(missing_docs)]

//! This crate provides types `Nil` and `Cons<H, T>`, which together allow for creating lists consisting of multiple types.
//! The types in the list are present in the type of the list, so that `Cons<i32, Cons<i64, Nil>>` contains an `i32` and an `i64`.
//! If type `T` is present exactly once in an `HList`, it is usually possible to allow the compiler to find the `T` in the `HList` by using the `Find` trait.

/// The empty `HList`.
pub struct Nil;

/// An `HList` with `H` at position 0, and `T` as the rest of the list.
pub struct Cons<H, T>(pub H, pub T);

/// A marker trait that `Nil` and `Cons<H, T>` satisfies.
/// Not currently used to enforce proper hlists, although this may change.
/// Provides the `push()` method
pub trait HList: Sized {
    /// Consumes the `HList`, and returns a new HList with `item` at the beginning.
    fn push<N>(self, item: N) -> Cons<N, Self> {
        Cons(item, self)
    }
}

impl HList for Nil {}
impl<H, T> HList for Cons<H, T> {}

/// Used as an index into an `HList`.
///
/// `Here` is 0, pointing to the head of the HList.
///
/// Users should normally allow type inference to create this type
#[allow(dead_code)]
pub enum Here {}

/// Used as an index into an `HList`.
///
/// `There<T>` is 1 + `T`.
///
/// Users should normally allow type inference to create this type.
#[allow(dead_code)]
pub struct There<T>(std::marker::PhantomData<T>);

/// `Find<T, I>` is implemented for an `HList` if index `I` of the `HList` is a `T`
///
/// Rust's type inferencer can often produce a correct `I`
/// if there is exactly one `T` in the `HList`.
///
/// ```rust
/// use hlist::{HList, Nil, Find};
///
/// // The type of list is Cons<i64, Cons<i32, Nil>>
/// let list = Nil.push(0i32).push(1i64);
///
/// // Here list satisfies the trait Find<i64, Here>.
/// // The compiler infers the second type parameter.
/// let a: i64 = *list.get();
/// assert!(a == 1);
///
/// // Here list satisfies the trait Find<i32, There<Here>>.
/// let b: i32 = *list.get();
/// assert!(b == 0);
/// ```
///
/// Functions that need to look up values of a type in an HList given to them should get the index from the call site:
///
/// ```rust
/// fn foo<I, L: Find<i32, I>>(list: &L) -> i32 {
///     *list.get()
/// }
/// let list = Nil.push("foo").push(5i32).push("bar");
/// assert!(foo(&list) == 5);
/// ```
///
/// When `foo()` is called, the compiler figures out the appropriate value for `I`.
pub trait Find<T, I> {
    /// Retrieves a `&T`.
    ///
    /// Allows for type inferencing to act like type-directed search.
    ///
    /// ```rust
    /// use hlist::{HList, Nil, Find}
    ///
    /// let list = Nil.push(0i32).push(1i64);
    /// let a: i64 = *list.get();
    /// assert!(a == 1);
    fn get(&self) -> &T;

    /// Retrieves a `&mut T`.
    ///
    /// Allows for type inferencing to act like type-directed search.
    ///
    /// ```rust
    /// use hlist::{HList, Nil, Find}
    ///
    /// let mut list = Nil.push(0i32).push(1i64);
    /// *list.get_mut() = 5i32;
    /// let a: i32 = *list.get()
    /// assert!(a == 5);
    fn get_mut(&mut self) -> &mut T;
}

impl<T, Tail> Find<T, Here> for Cons<T, Tail> {
    fn get(&self) -> &T {
        &self.0
    }
    fn get_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<Head, T, Tail, TailIndex> Find<T, There<TailIndex>> for Cons<Head, Tail>
    where Tail: Find<T, TailIndex> {
    fn get(&self) -> &T {
        self.1.get()
    }
    fn get_mut(&mut self) -> &mut T {
        self.1.get_mut()
    }
}

#[test]
fn test_get() {
    let list = Nil.push(5i32).push("Foo");
    let a: i32 = *list.get();
    let b: &str = *list.get();
    assert!(a == 5i32);
    assert!(b == "Foo");
}

#[test]
fn test_get_mut() {
    let mut list = Nil.push(5i32).push("Foo");
    *list.get_mut() = 6i32;
    *list.get_mut() = "Bar";
    let a: i32 = *list.get();
    let b: &str = *list.get();
    assert!(a == 6i32);
    assert!(b == "Bar");
}

#[test]
fn test_index_as_type_parameter() {
    fn foo<I, L: Find<i32, I>>(list: &L) -> i32 {
        *list.get()
    }
    let list = Nil.push("foo").push(5i32).push("bar");
    assert!(foo(&list) == 5);
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
#![allow(unused_imports)]

#![feature(test)]
extern crate rand;
extern crate test;

use test::Bencher;

#[test]
fn is_it_a_prime_number() {
    assert_eq!(true, is_prime(5));
    assert_eq!(true, is_prime_why_not(5));
}

#[test]
fn should_not_be_a_prime_number() {
    assert_eq!(false, is_prime(4));
    assert_eq!(false, is_prime_why_not(4));
}

#[test]
fn zero_is_not_a_prime_number() {
    assert_eq!(false, is_prime(0));
    assert_eq!(false, is_prime_why_not(0));
}

#[test]
fn one_is_not_a_prime_number() {
    assert_eq!(false, is_prime(1));
    assert_eq!(false, is_prime_why_not(1));
}

#[test]
fn prime_factorization_test(){
    let mut vec = Vec::new();
    vec.push(2);
    vec.push(2);
    vec.push(2);
    vec.push(3);
    vec.push(7);
    assert_eq!(vec, prime_factorization(168));
    vec = Vec::new();
    vec.push(2);
    vec.push(3);
    vec.push(17);
    assert_eq!(vec, prime_factorization(102));
}

#[test]
fn get_next_prime_number_test() {
    assert_eq!(79, get_next_prime_number(73));
}

#[test]
fn greatest_common_factor_test() {
    assert_eq!(6, greatest_common_factor(18,24));
}
//#[bench]
//fn bench_is_prime(b: &mut Bencher) {
//    b.iter(|| is_prime(rand::random::<i32>()));
//}

/// Tests for prime numbers.
///
/// # Examples
///
/// ```
/// use prime::is_prime;
///
/// println!("{}", prime::is_prime(5));
///
pub fn is_prime(x: i32) -> bool {
    let mut start: i64 = 2;
    while start <= (x as f64).sqrt() as i64 {
        if (x as i64) % start < 1 {
            return false;
        }
        start += 1;
    }
    return x > 1;
}

//#[bench]
//fn bench_is_prime_why_not(b: &mut Bencher) {
//      b.iter(||
//             for n in (0..10) {
//                test::black_box(is_prime_why_not(n));
//             });
//}

/// Tests for prime numbers and state why its not a prime number.
///
/// # Examples
///
/// ```
/// use prime::is_prime_why_not;
///
/// println!("{}", prime::is_prime_why_not(9));
///
pub fn is_prime_why_not(x: i32) -> bool {
    let mut start: i64 = 2;
    let mut return_value: bool = true;
    while start <= (x as f64).sqrt() as i64 {
        let m = (x as i64) % start;
        if m < 1 {
            println!("{} is divisible by {}.  {} * {} = {}", x, start, start, ((x as i64) / start), x);
            return_value = false;
        }
        start += 1;
    }
    if return_value == true {
        return_value = x > 1;
    }
    return return_value;
}

//#[bench]
//fn bench_get_next_prime_number(b: &mut Bencher) {
//    b.iter(||
//           for n in (1..10) {
//               test::black_box(get_next_prime_number(n));
//           });
//}

/// Returns the next available prime number.
///
/// # Examples
///
/// ```
/// use prime::get_next_prime_number;
///
/// println!("{}", prime::get_next_prime_number(9));
///
pub fn get_next_prime_number(n:i32) -> i32 {
    //println!("{}", n);
    let mut x: i32 = n;
    x += 1;
    while !is_prime(x) {
        x += 1;
    }
    return x;
}

//#[bench]
//fn bench_prime_factorization(b: &mut Bencher) {
//    b.iter(||
//           for n in (1..10) {
//                test::black_box(prime_factorization(n));
//           });
//}

/// Perform a prime factorization.
///
/// # Examples
///
/// ```
/// use prime::prime_factorization;
///
/// println!("{:?}", prime::prime_factorization(168));
///
pub fn prime_factorization(n:i32) -> Vec<i64> {
    let mut x:i64 = n as i64;
    let mut return_value = Vec::new();
    let mut start:i64 = 2;
    while !is_prime(x as i32) {
        let m = x % start;
        if m < 1 {
            return_value.push(start);
            x = x / start;
        } else {
            let s = start as i32;
            start = get_next_prime_number(s) as i64;                                                                  }
    }
    return_value.push(x);
    return return_value;
}

/// Perform a greatest common factor(gcf) calculation.
///
/// # Examples
///
/// ```
/// use prime::greatest_common_factor;
///
/// println!("{}", prime::greatest_common_factor(18,24));
///
pub fn greatest_common_factor(x:i32, y:i32) -> i32 {
    let mut vec_x = prime_factorization(x);
    let mut vec_y = prime_factorization(y);
    vec_x.dedup();
    vec_y.dedup();
    let mut m:Vec<i32> = Vec::new();
    for p in vec_x.iter() {
        for q in vec_y.iter() {
            if p == q {
                m.push(*p as i32);
            }
        }
    }
    let mut return_value = 1;
    for k in &m {
        return_value = return_value * k;
    }
    return return_value;
}

<commit_msg>added lcm<commit_after>#![allow(dead_code)]
#![allow(unused_imports)]

#![feature(test)]
extern crate rand;
extern crate test;

use test::Bencher;

#[test]
fn is_it_a_prime_number() {
    assert_eq!(true, is_prime(5));
    assert_eq!(true, is_prime_why_not(5));
}

#[test]
fn should_not_be_a_prime_number() {
    assert_eq!(false, is_prime(4));
    assert_eq!(false, is_prime_why_not(4));
}

#[test]
fn zero_is_not_a_prime_number() {
    assert_eq!(false, is_prime(0));
    assert_eq!(false, is_prime_why_not(0));
}

#[test]
fn one_is_not_a_prime_number() {
    assert_eq!(false, is_prime(1));
    assert_eq!(false, is_prime_why_not(1));
}

#[test]
fn prime_factorization_test(){
    let mut vec = Vec::new();
    vec.push(2);
    vec.push(2);
    vec.push(2);
    vec.push(3);
    vec.push(7);
    assert_eq!(vec, prime_factorization(168));
    vec = Vec::new();
    vec.push(2);
    vec.push(3);
    vec.push(17);
    assert_eq!(vec, prime_factorization(102));
}

#[test]
fn get_next_prime_number_test() {
    assert_eq!(79, get_next_prime_number(73));
}

#[test]
fn greatest_common_factor_test() {
    assert_eq!(6, greatest_common_factor(18,24));
}

#[test]
fn least_common_multiple_test() {
    assert_eq!(90, least_common_multiple(18,30));
}

//#[bench]
//fn bench_is_prime(b: &mut Bencher) {
//    b.iter(|| is_prime(rand::random::<i32>()));
//}

/// Tests for prime numbers.
///
/// # Examples
///
/// ```
/// use primapalooza::is_prime;
///
/// println!("{}", primapalooza::is_prime(5));
///
pub fn is_prime(x: i32) -> bool {
    let mut start: i64 = 2;
    while start <= (x as f64).sqrt() as i64 {
        if (x as i64) % start < 1 {
            return false;
        }
        start += 1;
    }
    return x > 1;
}

//#[bench]
//fn bench_is_prime_why_not(b: &mut Bencher) {
//      b.iter(||
//             for n in (0..10) {
//                test::black_box(is_prime_why_not(n));
//             });
//}

/// Tests for prime numbers and state why its not a prime number.
///
/// # Examples
///
/// ```
/// use primapalooza::is_prime_why_not;
///
/// println!("{}", primapalooza::is_prime_why_not(9));
///
pub fn is_prime_why_not(x: i32) -> bool {
    let mut start: i64 = 2;
    let mut return_value: bool = true;
    while start <= (x as f64).sqrt() as i64 {
        let m = (x as i64) % start;
        if m < 1 {
            println!("{} is divisible by {}.  {} * {} = {}", x, start, start, ((x as i64) / start), x);
            return_value = false;
        }
        start += 1;
    }
    if return_value == true {
        return_value = x > 1;
    }
    return return_value;
}

//#[bench]
//fn bench_get_next_prime_number(b: &mut Bencher) {
//    b.iter(||
//           for n in (1..10) {
//               test::black_box(get_next_prime_number(n));
//           });
//}

/// Returns the next available prime number.
///
/// # Examples
///
/// ```
/// use primapalooza::get_next_prime_number;
///
/// println!("{}", primapalooza::get_next_prime_number(9));
///
pub fn get_next_prime_number(n:i32) -> i32 {
    //println!("{}", n);
    let mut x: i32 = n;
    x += 1;
    while !is_prime(x) {
        x += 1;
    }
    return x;
}

//#[bench]
//fn bench_prime_factorization(b: &mut Bencher) {
//    b.iter(||
//           for n in (1..10) {
//                test::black_box(prime_factorization(n));
//           });
//}

/// Perform a prime factorization.
///
/// # Examples
///
/// ```
/// use primapalooza::prime_factorization;
///
/// println!("{:?}", primapalooza::prime_factorization(168));
///
pub fn prime_factorization(n:i32) -> Vec<i64> {
    let mut x:i64 = n as i64;
    let mut return_value = Vec::new();
    let mut start:i64 = 2;
    while !is_prime(x as i32) {
        let m = x % start;
        if m < 1 {
            return_value.push(start);
            x = x / start;
        } else {
            let s = start as i32;
            start = get_next_prime_number(s) as i64;                                                                  }
    }
    return_value.push(x);
    return return_value;
}

/// Perform a greatest common factor(gcf) calculation.
///
/// # Examples
///
/// ```
/// use primapalooza::greatest_common_factor;
///
/// println!("{}", primapalooza::greatest_common_factor(18,24));
///
pub fn greatest_common_factor(x:i32, y:i32) -> i32 {
    let mut vec_x = prime_factorization(x);
    let mut vec_y = prime_factorization(y);
    vec_x.dedup();
    vec_y.dedup();
    let mut m:Vec<i32> = Vec::new();
    for p in vec_x.iter() {
        for q in vec_y.iter() {
            if p == q {
                m.push(*p as i32);
            }
        }
    }
    let mut return_value = 1;
    for k in &m {
        return_value = return_value * k;
    }
    return return_value;
}

/// Perform a least common multiple(lcm) calculation.
///
/// # Examples
///
/// ```
/// use primapalooza::least_common_multiple;
///
/// println!("{}", primapalooza::least_common_multiple(18,24));
///
pub fn least_common_multiple(x:i32, y:i32) -> i32 {
    let gcf = greatest_common_factor(x, y);
    if x % gcf < 1 {
        (x/gcf) * y
    } else {
        (y/gcf) * x
    }
}

<|endoftext|>


<commit_before>#![doc(html_logo_url = "https://cdn.rawgit.com/urschrei/polylabel-rs/7a07336e85572eb5faaf0657c2383d7de5620cd8/ell.svg",
       html_root_url = "https://urschrei.github.io/polylabel-rs/")]
//! This crate provides a Rust implementation of the [Polylabel](https://github.com/mapbox/polylabel) algorithm
//! for finding the optimum position of a polygon label.
use std::cmp::Ordering;
use std::collections::BinaryHeap;

extern crate num_traits;
use self::num_traits::{Float, FromPrimitive, Signed};

extern crate geo;
use self::geo::{Point, Polygon};
use self::geo::algorithm::boundingbox::BoundingBox;
use self::geo::algorithm::distance::Distance;
use self::geo::algorithm::area::Area;
use self::geo::algorithm::centroid::Centroid;
use self::geo::algorithm::contains::Contains;

mod ffi;
pub use ffi::{polylabel_ffi, Array, Position, WrapperArray};

#[doc(hidden)]
#[allow(dead_code)]
pub extern "C" fn spare() {
    println!("");
}

/// Represention of a Quadtree cell
#[derive(Debug)]
struct Qcell<T>
where
    T: Float + Signed,
{
    centroid: Point<T>,
    // Half the cell size
    h: T,
    // Distance from centroid to polygon
    distance: T,
    // Maximum distance to polygon within a cell
    max_distance: T,
}

impl<T> Qcell<T>
where
    T: Float + Signed,
{
    fn new(x: T, y: T, h: T, distance: T, max_distance: T) -> Qcell<T> {
        Qcell {
            centroid: Point::new(x, y),
            h: h,
            distance: distance,
            max_distance: max_distance,
        }
    }
}

impl<T> Ord for Qcell<T>
where
    T: Float + Signed,
{
    fn cmp(&self, other: &Qcell<T>) -> std::cmp::Ordering {
        self.max_distance.partial_cmp(&other.max_distance).unwrap()
    }
}
impl<T> PartialOrd for Qcell<T>
where
    T: Float + Signed,
{
    fn partial_cmp(&self, other: &Qcell<T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}
impl<T> Eq for Qcell<T>
where
    T: Float + Signed,
{
}
impl<T> PartialEq for Qcell<T>
where
    T: Float + Signed,
{
    fn eq(&self, other: &Qcell<T>) -> bool
    where
        T: Float,
    {
        self.max_distance == other.max_distance
    }
}

/// Signed distance from a Qcell's centroid to a Polygon's outline
/// Returned value is negative if the point is outside the polygon's exterior ring
fn signed_distance<T>(x: &T, y: &T, polygon: &Polygon<T>) -> T
where
    T: Float,
{
    let point = Point::new(*x, *y);
    let inside = polygon.contains(&point);
    // Use LineString distance, because Polygon distance returns 0.0 for inside
    let distance = point.distance(&polygon.exterior);
    if inside {
        distance
    } else {
        -distance
    }
}

/// Add a new Quadtree node made up of four `Qcell`s to the binary heap
fn add_quad<T>(
    mpq: &mut BinaryHeap<Qcell<T>>,
    cell: &Qcell<T>,
    new_height: &T,
    polygon: &Polygon<T>,
) where
    T: Float + Signed,
{
    let two = T::one() + T::one();
    let centroid_x = cell.centroid.x();
    let centroid_y = cell.centroid.y();
    for combo in &[
        (centroid_x - *new_height, centroid_y - *new_height),
        (centroid_x + *new_height, centroid_y - *new_height),
        (centroid_x - *new_height, centroid_y + *new_height),
        (centroid_x + *new_height, centroid_y + *new_height),
    ] {
        let mut new_dist = signed_distance(&combo.0, &combo.1, polygon);
        mpq.push(Qcell::new(
            combo.0,
            combo.1,
            *new_height,
            new_dist,
            new_dist + *new_height * two.sqrt(),
        ));
    }
}

/// Calculate a Polygon's ideal label position by calculating its ✨pole of inaccessibility✨
///
/// The calculation uses an [iterative grid-based algorithm](https://github.com/mapbox/polylabel#how-the-algorithm-works).
///
/// # Examples
///
/// ```
/// use polylabel::polylabel;
/// extern crate geo;
/// use self::geo::{Point, LineString, Polygon};
///
/// // An approximate `L` shape
/// let coords = vec![
///    (0.0, 0.0),
///    (4.0, 0.0),
///    (4.0, 1.0),
///    (1.0, 1.0),
///    (1.0, 4.0),
///    (0.0, 4.0),
///    (0.0, 0.0)];
///
/// let poly = Polygon::new(coords.into(), vec![]);
///
/// // Its centroid lies outside the polygon
/// assert_eq!(poly.centroid(), Point::new(1.3571428571428572, 1.3571428571428572));
///
/// let label_position = polylabel(&poly, &1.0);
/// // Optimum label position is inside the polygon
/// assert_eq!(label_position, Point::new(0.5625, 0.5625));
/// ```
///
pub fn polylabel<T>(polygon: &Polygon<T>, tolerance: &T) -> Point<T>
where
    T: Float + FromPrimitive + Signed,
{
    // special case for degenerate polygons
    if polygon.area() == T::zero() {
        // best_cell = Qcell {
        //     centroid = Point::new(polygon.exterior.0[0].x(), polygon.exterior.0[0].y())
        //     h: T::zero(),
        //     distance: distance,
        //     max_distance: max_distance
        // };
        return Point::new(T::zero(), T::zero());
    }
    let two = T::one() + T::one();
    // Initial best cell values
    let centroid = polygon.centroid().unwrap();
    let bbox = polygon.bbox().unwrap();
    let width = bbox.xmax - bbox.xmin;
    let height = bbox.ymax - bbox.ymin;
    let cell_size = width.min(height);
    // Special case for degenerate polygons
    if cell_size == T::zero() {
        return Point::new(bbox.xmin, bbox.ymin);
    }
    let mut h = cell_size / two;
    let distance = signed_distance(&centroid.x(), &centroid.y(), polygon);
    let max_distance = distance + T::zero() * two.sqrt();

    let mut best_cell = Qcell {
        centroid: Point::new(centroid.x(), centroid.y()),
        h: T::zero(),
        distance: distance,
        max_distance: max_distance,
    };

    // special case for rectangular polygons
    let bbox_cell_dist = signed_distance(
        &(bbox.xmin + width / two),
        &(bbox.ymin + height / two),
        polygon,
    );
    let bbox_cell = Qcell {
        centroid: Point::new(bbox.xmin + width / two, bbox.ymin + height / two),
        h: T::zero(),
        distance: bbox_cell_dist,
        max_distance: bbox_cell_dist + T::zero() * two.sqrt(),
    };

    if bbox_cell.distance > best_cell.distance {
        best_cell = bbox_cell;
    }

    // Priority queue
    let mut cell_queue: BinaryHeap<Qcell<T>> = BinaryHeap::new();
    // Build an initial quadtree node, which covers the Polygon
    let mut x = bbox.xmin;
    let mut y;
    while x < bbox.xmax {
        y = bbox.ymin;
        while y < bbox.ymax {
            let latest_dist = signed_distance(&(x + h), &(y + h), polygon);
            cell_queue.push(Qcell {
                centroid: Point::new(x + h, y + h),
                h: h,
                distance: latest_dist,
                max_distance: latest_dist + h * two.sqrt(),
            });
            y = y + cell_size;
        }
        x = x + cell_size;
    }
    // Now try to find better solutions
    while !cell_queue.is_empty() {
        let cell = cell_queue.pop().unwrap();
        // Update the best cell if we find a cell with greater distance
        if cell.distance > best_cell.distance {
            best_cell.centroid = Point::new(cell.centroid.x(), cell.centroid.y());
            best_cell.h = cell.h;
            best_cell.distance = cell.distance;
            best_cell.max_distance = cell.max_distance;
        }
        // Bail out of this iteration if we can't find a better solution
        if cell.max_distance - best_cell.distance <= *tolerance {
            continue;
        }
        // Otherwise, add a new quadtree node and start again
        h = cell.h / two;
        add_quad(&mut cell_queue, &cell, &h, polygon);
    }
    // We've exhausted the queue, so return the best solution we've found
    Point::new(best_cell.centroid.x(), best_cell.centroid.y())
}

#[cfg(test)]
mod tests {
    use std::collections::BinaryHeap;
    use super::{polylabel, Qcell};
    use geo::{Point, Polygon};
    use geo::contains::Contains;
    #[test]
    // polygons are those used in Shapely's tests
    fn test_polylabel() {
        let coords = include!("poly1.rs");
        let poly = Polygon::new(coords.into(), vec![]);
        let res = polylabel(&poly, &10.000);
        assert_eq!(res, Point::new(59.35615556364569, 121.83919629746435));
    }
    #[test]
    // does a concave polygon contain the calculated point?
    // relevant because the centroid lies outside the polygon in this case
    fn test_concave() {
        let coords = include!("poly2.rs");
        let poly = Polygon::new(coords.into(), vec![]);
        let res = polylabel(&poly, &1.0);
        assert!(poly.contains(&res));
    }
    #[test]
    fn polygon_l_test() {
        // an L shape
        let coords = vec![
            (0.0, 0.0),
            (4.0, 0.0),
            (4.0, 1.0),
            (1.0, 1.0),
            (1.0, 4.0),
            (0.0, 4.0),
            (0.0, 0.0),
        ];
        let poly = Polygon::new(coords.into(), vec![]);
        let res = polylabel(&poly, &0.10);
        assert_eq!(res, Point::new(0.5625, 0.5625));
    }
    #[test]
    fn degenerate_polygon_test() {
        let a_coords = vec![(0.0, 0.0), (1.0, 0.0), (2.0, 0.0), (0.0, 0.0)];
        let a_poly = Polygon::new(a_coords.into(), vec![]);
        let a_res = polylabel(&a_poly, &1.0);
        assert_eq!(a_res, Point::new(0.0, 0.0));
    }
    #[test]
    fn degenerate_polygon_test_2() {
        let b_coords = vec![(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (1.0, 0.0), (0.0, 0.0)];
        let b_poly = Polygon::new(b_coords.into(), vec![]);
        let b_res = polylabel(&b_poly, &1.0);
        assert_eq!(b_res, Point::new(0.0, 0.0));
    }
    #[test]
    // Is our priority queue behaving as it should?
    fn test_queue() {
        let a = Qcell {
            centroid: Point::new(1.0, 2.0),
            h: 3.0,
            distance: 4.0,
            max_distance: 8.0,
        };
        let b = Qcell {
            centroid: Point::new(1.0, 2.0),
            h: 3.0,
            distance: 4.0,
            max_distance: 7.0,
        };
        let c = Qcell {
            centroid: Point::new(1.0, 2.0),
            h: 3.0,
            distance: 4.0,
            max_distance: 9.0,
        };
        let mut v = vec![];
        v.push(a);
        v.push(b);
        v.push(c);
        let mut q = BinaryHeap::from(v);
        assert_eq!(q.pop().unwrap().max_distance, 9.0);
        assert_eq!(q.pop().unwrap().max_distance, 8.0);
        assert_eq!(q.pop().unwrap().max_distance, 7.0);
    }
}
<commit_msg>Actually use the Qcell's new() method<commit_after>#![doc(html_logo_url = "https://cdn.rawgit.com/urschrei/polylabel-rs/7a07336e85572eb5faaf0657c2383d7de5620cd8/ell.svg",
       html_root_url = "https://urschrei.github.io/polylabel-rs/")]
//! This crate provides a Rust implementation of the [Polylabel](https://github.com/mapbox/polylabel) algorithm
//! for finding the optimum position of a polygon label.
use std::cmp::Ordering;
use std::collections::BinaryHeap;

extern crate num_traits;
use self::num_traits::{Float, FromPrimitive, Signed};

extern crate geo;
use self::geo::{Point, Polygon};
use self::geo::algorithm::boundingbox::BoundingBox;
use self::geo::algorithm::distance::Distance;
use self::geo::algorithm::area::Area;
use self::geo::algorithm::centroid::Centroid;
use self::geo::algorithm::contains::Contains;

mod ffi;
pub use ffi::{polylabel_ffi, Array, Position, WrapperArray};

#[doc(hidden)]
#[allow(dead_code)]
pub extern "C" fn spare() {
    println!("");
}

/// Represention of a Quadtree cell
#[derive(Debug)]
struct Qcell<T>
where
    T: Float + Signed,
{
    centroid: Point<T>,
    // Half the cell size
    h: T,
    // Distance from centroid to polygon
    distance: T,
    // Maximum distance to polygon within a cell
    max_distance: T,
}

impl<T> Qcell<T>
where
    T: Float + Signed,
{
    fn new(x: T, y: T, h: T, distance: T, max_distance: T) -> Qcell<T> {
        Qcell {
            centroid: Point::new(x, y),
            h: h,
            distance: distance,
            max_distance: max_distance,
        }
    }
}

impl<T> Ord for Qcell<T>
where
    T: Float + Signed,
{
    fn cmp(&self, other: &Qcell<T>) -> std::cmp::Ordering {
        self.max_distance.partial_cmp(&other.max_distance).unwrap()
    }
}
impl<T> PartialOrd for Qcell<T>
where
    T: Float + Signed,
{
    fn partial_cmp(&self, other: &Qcell<T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}
impl<T> Eq for Qcell<T>
where
    T: Float + Signed,
{
}
impl<T> PartialEq for Qcell<T>
where
    T: Float + Signed,
{
    fn eq(&self, other: &Qcell<T>) -> bool
    where
        T: Float,
    {
        self.max_distance == other.max_distance
    }
}

/// Signed distance from a Qcell's centroid to a Polygon's outline
/// Returned value is negative if the point is outside the polygon's exterior ring
fn signed_distance<T>(x: &T, y: &T, polygon: &Polygon<T>) -> T
where
    T: Float,
{
    let point = Point::new(*x, *y);
    let inside = polygon.contains(&point);
    // Use LineString distance, because Polygon distance returns 0.0 for inside
    let distance = point.distance(&polygon.exterior);
    if inside {
        distance
    } else {
        -distance
    }
}

/// Add a new Quadtree node made up of four `Qcell`s to the binary heap
fn add_quad<T>(
    mpq: &mut BinaryHeap<Qcell<T>>,
    cell: &Qcell<T>,
    new_height: &T,
    polygon: &Polygon<T>,
) where
    T: Float + Signed,
{
    let two = T::one() + T::one();
    let centroid_x = cell.centroid.x();
    let centroid_y = cell.centroid.y();
    for combo in &[
        (centroid_x - *new_height, centroid_y - *new_height),
        (centroid_x + *new_height, centroid_y - *new_height),
        (centroid_x - *new_height, centroid_y + *new_height),
        (centroid_x + *new_height, centroid_y + *new_height),
    ] {
        let mut new_dist = signed_distance(&combo.0, &combo.1, polygon);
        mpq.push(Qcell::new(
            combo.0,
            combo.1,
            *new_height,
            new_dist,
            new_dist + *new_height * two.sqrt(),
        ));
    }
}

/// Calculate a Polygon's ideal label position by calculating its ✨pole of inaccessibility✨
///
/// The calculation uses an [iterative grid-based algorithm](https://github.com/mapbox/polylabel#how-the-algorithm-works).
///
/// # Examples
///
/// ```
/// use polylabel::polylabel;
/// extern crate geo;
/// use self::geo::{Point, LineString, Polygon};
///
/// // An approximate `L` shape
/// let coords = vec![
///    (0.0, 0.0),
///    (4.0, 0.0),
///    (4.0, 1.0),
///    (1.0, 1.0),
///    (1.0, 4.0),
///    (0.0, 4.0),
///    (0.0, 0.0)];
///
/// let poly = Polygon::new(coords.into(), vec![]);
///
/// // Its centroid lies outside the polygon
/// assert_eq!(poly.centroid(), Point::new(1.3571428571428572, 1.3571428571428572));
///
/// let label_position = polylabel(&poly, &1.0);
/// // Optimum label position is inside the polygon
/// assert_eq!(label_position, Point::new(0.5625, 0.5625));
/// ```
///
pub fn polylabel<T>(polygon: &Polygon<T>, tolerance: &T) -> Point<T>
where
    T: Float + FromPrimitive + Signed,
{
    // special case for degenerate polygons
    if polygon.area() == T::zero() {
        // best_cell = Qcell {
        //     centroid = Point::new(polygon.exterior.0[0].x(), polygon.exterior.0[0].y())
        //     h: T::zero(),
        //     distance: distance,
        //     max_distance: max_distance
        // };
        return Point::new(T::zero(), T::zero());
    }
    let two = T::one() + T::one();
    // Initial best cell values
    let centroid = polygon.centroid().unwrap();
    let bbox = polygon.bbox().unwrap();
    let width = bbox.xmax - bbox.xmin;
    let height = bbox.ymax - bbox.ymin;
    let cell_size = width.min(height);
    // Special case for degenerate polygons
    if cell_size == T::zero() {
        return Point::new(bbox.xmin, bbox.ymin);
    }
    let mut h = cell_size / two;
    let distance = signed_distance(&centroid.x(), &centroid.y(), polygon);
    let max_distance = distance + T::zero() * two.sqrt();

    let mut best_cell = Qcell::new(
        centroid.x(),
        centroid.y(),
        T::zero(),
        distance,
        max_distance,
    );

    // special case for rectangular polygons
    let bbox_cell_dist = signed_distance(
        &(bbox.xmin + width / two),
        &(bbox.ymin + height / two),
        polygon,
    );
    let bbox_cell = Qcell {
        centroid: Point::new(bbox.xmin + width / two, bbox.ymin + height / two),
        h: T::zero(),
        distance: bbox_cell_dist,
        max_distance: bbox_cell_dist + T::zero() * two.sqrt(),
    };

    if bbox_cell.distance > best_cell.distance {
        best_cell = bbox_cell;
    }

    // Priority queue
    let mut cell_queue: BinaryHeap<Qcell<T>> = BinaryHeap::new();
    // Build an initial quadtree node, which covers the Polygon
    let mut x = bbox.xmin;
    let mut y;
    while x < bbox.xmax {
        y = bbox.ymin;
        while y < bbox.ymax {
            let latest_dist = signed_distance(&(x + h), &(y + h), polygon);
            cell_queue.push(Qcell {
                centroid: Point::new(x + h, y + h),
                h: h,
                distance: latest_dist,
                max_distance: latest_dist + h * two.sqrt(),
            });
            y = y + cell_size;
        }
        x = x + cell_size;
    }
    // Now try to find better solutions
    while !cell_queue.is_empty() {
        let cell = cell_queue.pop().unwrap();
        // Update the best cell if we find a cell with greater distance
        if cell.distance > best_cell.distance {
            best_cell.centroid = Point::new(cell.centroid.x(), cell.centroid.y());
            best_cell.h = cell.h;
            best_cell.distance = cell.distance;
            best_cell.max_distance = cell.max_distance;
        }
        // Bail out of this iteration if we can't find a better solution
        if cell.max_distance - best_cell.distance <= *tolerance {
            continue;
        }
        // Otherwise, add a new quadtree node and start again
        h = cell.h / two;
        add_quad(&mut cell_queue, &cell, &h, polygon);
    }
    // We've exhausted the queue, so return the best solution we've found
    Point::new(best_cell.centroid.x(), best_cell.centroid.y())
}

#[cfg(test)]
mod tests {
    use std::collections::BinaryHeap;
    use super::{polylabel, Qcell};
    use geo::{Point, Polygon};
    use geo::contains::Contains;
    #[test]
    // polygons are those used in Shapely's tests
    fn test_polylabel() {
        let coords = include!("poly1.rs");
        let poly = Polygon::new(coords.into(), vec![]);
        let res = polylabel(&poly, &10.000);
        assert_eq!(res, Point::new(59.35615556364569, 121.83919629746435));
    }
    #[test]
    // does a concave polygon contain the calculated point?
    // relevant because the centroid lies outside the polygon in this case
    fn test_concave() {
        let coords = include!("poly2.rs");
        let poly = Polygon::new(coords.into(), vec![]);
        let res = polylabel(&poly, &1.0);
        assert!(poly.contains(&res));
    }
    #[test]
    fn polygon_l_test() {
        // an L shape
        let coords = vec![
            (0.0, 0.0),
            (4.0, 0.0),
            (4.0, 1.0),
            (1.0, 1.0),
            (1.0, 4.0),
            (0.0, 4.0),
            (0.0, 0.0),
        ];
        let poly = Polygon::new(coords.into(), vec![]);
        let res = polylabel(&poly, &0.10);
        assert_eq!(res, Point::new(0.5625, 0.5625));
    }
    #[test]
    fn degenerate_polygon_test() {
        let a_coords = vec![(0.0, 0.0), (1.0, 0.0), (2.0, 0.0), (0.0, 0.0)];
        let a_poly = Polygon::new(a_coords.into(), vec![]);
        let a_res = polylabel(&a_poly, &1.0);
        assert_eq!(a_res, Point::new(0.0, 0.0));
    }
    #[test]
    fn degenerate_polygon_test_2() {
        let b_coords = vec![(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (1.0, 0.0), (0.0, 0.0)];
        let b_poly = Polygon::new(b_coords.into(), vec![]);
        let b_res = polylabel(&b_poly, &1.0);
        assert_eq!(b_res, Point::new(0.0, 0.0));
    }
    #[test]
    // Is our priority queue behaving as it should?
    fn test_queue() {
        let a = Qcell {
            centroid: Point::new(1.0, 2.0),
            h: 3.0,
            distance: 4.0,
            max_distance: 8.0,
        };
        let b = Qcell {
            centroid: Point::new(1.0, 2.0),
            h: 3.0,
            distance: 4.0,
            max_distance: 7.0,
        };
        let c = Qcell {
            centroid: Point::new(1.0, 2.0),
            h: 3.0,
            distance: 4.0,
            max_distance: 9.0,
        };
        let mut v = vec![];
        v.push(a);
        v.push(b);
        v.push(c);
        let mut q = BinaryHeap::from(v);
        assert_eq!(q.pop().unwrap().max_distance, 9.0);
        assert_eq!(q.pop().unwrap().max_distance, 8.0);
        assert_eq!(q.pop().unwrap().max_distance, 7.0);
    }
}
<|endoftext|>


<commit_before>/* Copyright 2017 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pub use parser::Parser;
pub use parser::ParserState;
pub use parser::SectionCode;
pub use parser::Operator;
pub use parser::Type;
pub use parser::CustomSectionKind;
pub use parser::NameType;
pub use parser::Naming;
pub use parser::LocalName;
pub use parser::NameEntry;
pub use parser::ExternalKind;
pub use parser::FuncType;
pub use parser::ResizableLimits;
pub use parser::TableType;
pub use parser::MemoryType;
pub use parser::GlobalType;
pub use parser::MemoryImmediate;
pub use parser::BrTable;
pub use parser::ImportSectionEntryType;
pub use parser::RelocType;
pub use parser::RelocEntry;
pub use parser::LinkingType;

mod parser;
mod tests;
<commit_msg>Add description.<commit_after>/* Copyright 2017 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! A simple event-driven library for parsing WebAssembly binary files
//! (or streams).
//!
//! The parser library reports events as they happend and only stores
//! parsing information for a brief period of time, making it very fast
//! and memory-efficient. The event-driven model, however, has some drawbacks.
//! If you need random access to the entire WebAssembly data-structure,
//! this is not the right library for you. You could however, build such
//! a data-structure using this library.

pub use parser::Parser;
pub use parser::ParserState;
pub use parser::SectionCode;
pub use parser::Operator;
pub use parser::Type;
pub use parser::CustomSectionKind;
pub use parser::NameType;
pub use parser::Naming;
pub use parser::LocalName;
pub use parser::NameEntry;
pub use parser::ExternalKind;
pub use parser::FuncType;
pub use parser::ResizableLimits;
pub use parser::TableType;
pub use parser::MemoryType;
pub use parser::GlobalType;
pub use parser::MemoryImmediate;
pub use parser::BrTable;
pub use parser::ImportSectionEntryType;
pub use parser::RelocType;
pub use parser::RelocEntry;
pub use parser::LinkingType;

mod parser;
mod tests;
<|endoftext|>


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

#![crate_name = "taglib"]
#![crate_type = "lib"]

extern crate libc;
extern crate taglib_sys as sys;

use libc::c_char;
use std::ffi::{CString, CStr};

use sys as ll;

fn c_str_to_str(c_str: *const c_char) -> String {
    if c_str.is_null() {
        String::new()
    } else {
        let bytes = unsafe { CStr::from_ptr(c_str).to_bytes() };
        String::from_utf8_lossy(bytes).to_string()
    }
}

/// A representation of an audio file, with meta-data and properties.
pub struct File {
    raw: *mut ll::TagLib_File,
}

/// The abstract meta-data container for audio files
///
/// Each `Tag` instance can only be created by the `taglib::File::tag()`
/// method.
#[allow(dead_code)]
pub struct Tag<'a> {
    raw: *mut ll::TagLib_Tag,
    file: &'a File,
}

/// Common audio file properties.
///
/// Instances of `AudioProperties` can only be created through the
/// `taglib::File::audioproperties()` method.
#[allow(dead_code)]
pub struct AudioProperties<'a> {
    raw: *const ll::TagLib_AudioProperties,
    file: &'a File,
}

impl<'a> Tag<'a> {
    /// Returns the track name, or an empty string if no track name is present.
    pub fn title(&self) -> String {
        let res = unsafe { ll::taglib_tag_title(self.raw) };
        c_str_to_str(res)
    }

    /// Sets the track name.
    pub fn set_title(&mut self, title: &str) {
        let cs = CString::new(title).unwrap();
        let s = cs.as_ptr();
        unsafe {
            ll::taglib_tag_set_title(self.raw, s);
        }
    }

    /// Returns the artist name, or an empty string if no artist name is present.
    pub fn artist(&self) -> String {
        let res = unsafe { ll::taglib_tag_artist(self.raw) };
        c_str_to_str(res)
    }

    /// Sets the artist name.
    pub fn set_artist(&mut self, artist: &str) {
        let cs = CString::new(artist).unwrap();
        let s = cs.as_ptr();
        unsafe {
            ll::taglib_tag_set_artist(self.raw, s);
        }
    }

    /// Returns the album name, or an empty string if no album name is present.
    pub fn album(&self) -> String {
        let res = unsafe { ll::taglib_tag_album(self.raw) };
        c_str_to_str(res)
    }

    /// Sets the album name.
    pub fn set_album(&mut self, album: &str) {
        let cs = CString::new(album).unwrap();
        let s = cs.as_ptr();
        unsafe {
            ll::taglib_tag_set_album(self.raw, s);
        }
    }

    /// Returns the track comment, or an empty string if no track comment is
    /// present.
    pub fn comment(&self) -> String {
        let res = unsafe { ll::taglib_tag_comment(self.raw) };
        c_str_to_str(res)
    }

    /// Sets the track comment.
    pub fn set_comment(&mut self, comment: &str) {
        let cs = CString::new(comment).unwrap();
        let s = cs.as_ptr();
        unsafe {
            ll::taglib_tag_set_comment(self.raw, s);
        }
    }

    /// Returns the genre name, or an empty string if no genre name is present.
    pub fn genre(&self) -> String {
        let res = unsafe { ll::taglib_tag_genre(self.raw) };
        c_str_to_str(res)
    }

    /// Sets the genre name.
    pub fn set_genre(&mut self, genre: &str) {
        let cs = CString::new(genre).unwrap();
        let s = cs.as_ptr();
        unsafe {
            ll::taglib_tag_set_genre(self.raw, s);
        }
    }

    /// Returns the year, or 0 if no year is present.
    pub fn year(&self) -> u32 {
        unsafe { ll::taglib_tag_year(self.raw) as u32 }
    }

    /// Sets the year.
    pub fn set_year(&mut self, year: u32) {
        unsafe {
            ll::taglib_tag_set_year(self.raw, year);
        }
    }

    /// Returns the track number, or 0 if no track number is present.
    pub fn track(&self) -> u32 {
        unsafe { ll::taglib_tag_track(self.raw) as u32 }
    }

    /// Sets the track number.
    pub fn set_track(&mut self, track: u32) {
        unsafe {
            ll::taglib_tag_set_track(self.raw, track);
        }
    }
}

impl<'a> AudioProperties<'a> {
    /// Returns the length, in seconds, of the track.
    pub fn length(&self) -> u32 {
        unsafe { ll::taglib_audioproperties_length(self.raw) as u32 }
    }

    /// Returns the most appropriate bit rate for the track, in kB/s.
    /// For constant bit rate formats, the returned value is the bit
    /// rate of the file; for variable bit rate formats this is either
    /// the average or the nominal bit rate.
    pub fn bitrate(&self) -> u32 {
        unsafe { ll::taglib_audioproperties_bitrate(self.raw) as u32 }
    }

    /// Returns the sample rate, in Hz.
    pub fn samplerate(&self) -> u32 {
        unsafe { ll::taglib_audioproperties_samplerate(self.raw) as u32 }
    }

    /// Returns the number of audio channels.
    pub fn channels(&self) -> u32 {
        unsafe { ll::taglib_audioproperties_channels(self.raw) as u32 }
    }
}

#[derive(Copy, Clone, PartialEq)]
pub enum FileType {
    /// MPEG file
    MPEG = ll::TAGLIB_FILE_MPEG as isize,
    /// Ogg/Vorbis file
    OggVorbis = ll::TAGLIB_FILE_OGG_VORBIS as isize,
    /// FLAC file
    FLAC = ll::TAGLIB_FILE_FLAC as isize,
    /// MPC file
    MPC = ll::TAGLIB_FILE_MPC as isize,
    /// Ogg/FLAC file
    OggFlac = ll::TAGLIB_FILE_OGG_FLAC as isize,
    /// WavPack file
    WavPack = ll::TAGLIB_FILE_WAV_PACK as isize,
    /// Ogg/Speex file
    Speex = ll::TAGLIB_FILE_SPEEX as isize,
    /// TrueAudio file
    TrueAudio = ll::TAGLIB_FILE_TRUE_AUDIO as isize,
    /// MP4 file
    MP4 = ll::TAGLIB_FILE_MP4 as isize,
    /// ASF file
    ASF = ll::TAGLIB_FILE_ASF as isize,
}

#[derive(Debug)]
pub enum FileError {
    /// The file is an invalid or an unrecognized audio container
    InvalidFile,
    /// The file name is invalid
    InvalidFileName,
    /// No meta-data is available
    NoAvailableTag,
    /// No audio properties are available
    NoAvailableAudioProperties,
}

impl Drop for File {
    fn drop(&mut self) {
        unsafe {
            ll::taglib_file_free(self.raw);
        }
    }
}

impl File {
    /// Creates a new `taglib::File` for the given `filename`.
    pub fn new(filename: &str) -> Result<File, FileError> {
        let filename_c = match CString::new(filename) {
            Ok(s) => s,
            _ => return Err(FileError::InvalidFileName),
        };

        let filename_c_ptr = filename_c.as_ptr();

        let f = unsafe { ll::taglib_file_new(filename_c_ptr) };
        if f.is_null() {
            return Err(FileError::InvalidFile);
        }

        Ok(File { raw: f })
    }

    /// Creates a new `taglib::File` for the given `filename` and type of file.
    pub fn new_type(filename: &str, filetype: FileType) -> Result<File, FileError> {
        let filename_c = match CString::new(filename) {
            Ok(s) => s,
            _ => return Err(FileError::InvalidFileName),
        };

        let filename_c_ptr = filename_c.as_ptr();
        let f = unsafe { ll::taglib_file_new_type(filename_c_ptr, filetype as u32) };
        if f.is_null() {
            return Err(FileError::InvalidFile);
        }

        Ok(File { raw: f })
    }

    /// Returns the `taglib::Tag` instance for the given file.
    pub fn tag(&self) -> Result<Tag, FileError> {
        let res = unsafe { ll::taglib_file_tag(self.raw) };

        if res.is_null() {
            Err(FileError::NoAvailableTag)
        } else {
            Ok(Tag {
                raw: res,
                file: self,
            })
        }
    }

    /// Returns whether the file is valid.
    pub fn is_valid(&self) -> bool {
        unsafe { ll::taglib_file_is_valid(self.raw) != 0 }
    }

    /// Returns the `taglib::AudioProperties` instance for the given file.
    pub fn audioproperties(&self) -> Result<AudioProperties, FileError> {
        let res = unsafe { ll::taglib_file_audioproperties(self.raw) };

        if res.is_null() {
            Err(FileError::NoAvailableAudioProperties)
        } else {
            Ok(AudioProperties {
                raw: res,
                file: self,
            })
        }
    }

    /// Updates the meta-data of the file.
    pub fn save(&self) -> bool {
        unsafe { ll::taglib_file_save(self.raw) != 0 }
    }
}

/// Fixture creation:
/// ffmpeg -t 0.01 -f s16le -i /dev/zero test.mp3
/// kid3-cli -c 'set artist "Artist"' test.mp3
#[cfg(test)]
mod test {
    const TEST_MP3: &'static str = "fixtures/test.mp3";

    use super::*;
    use std::fs;

    #[test]
    fn test_get_tag() {
        let file = File::new(TEST_MP3).unwrap();
        let tag = file.tag().unwrap();
        assert_eq!(tag.artist(), "Artist");
    }

    #[test]
    fn test_set_tag() {
        let temp_fn = "fixtures/temp.mp3";
        fs::copy(TEST_MP3, temp_fn).unwrap();
        let file = File::new(temp_fn).unwrap();
        let mut tag = file.tag().unwrap();

        tag.set_artist("Not Artist");
        file.save();

        assert_eq!(tag.artist(), "Not Artist");

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

#![crate_name = "taglib"]
#![crate_type = "lib"]

extern crate libc;
extern crate taglib_sys as sys;

use libc::c_char;
use std::ffi::{CString, CStr};

use sys as ll;

fn c_str_to_str(c_str: *const c_char) -> String {
    if c_str.is_null() {
        String::new()
    } else {
        let bytes = unsafe { CStr::from_ptr(c_str).to_bytes() };
        String::from_utf8_lossy(bytes).to_string()
    }
}

/// A representation of an audio file, with meta-data and properties.
pub struct File {
    raw: *mut ll::TagLib_File,
}

/// The abstract meta-data container for audio files
///
/// Each `Tag` instance can only be created by the `taglib::File::tag()`
/// method.
#[allow(dead_code)]
pub struct Tag<'a> {
    raw: *mut ll::TagLib_Tag,
    file: &'a File,
}

/// Common audio file properties.
///
/// Instances of `AudioProperties` can only be created through the
/// `taglib::File::audioproperties()` method.
#[allow(dead_code)]
pub struct AudioProperties<'a> {
    raw: *const ll::TagLib_AudioProperties,
    file: &'a File,
}

impl<'a> Tag<'a> {
    /// Returns the track name, or an empty string if no track name is present.
    pub fn title(&self) -> String {
        let res = unsafe { ll::taglib_tag_title(self.raw) };
        c_str_to_str(res)
    }

    /// Sets the track name.
    pub fn set_title(&mut self, title: &str) {
        let cs = CString::new(title).unwrap();
        let s = cs.as_ptr();
        unsafe {
            ll::taglib_tag_set_title(self.raw, s);
        }
    }

    /// Returns the artist name, or an empty string if no artist name is present.
    pub fn artist(&self) -> String {
        let res = unsafe { ll::taglib_tag_artist(self.raw) };
        c_str_to_str(res)
    }

    /// Sets the artist name.
    pub fn set_artist(&mut self, artist: &str) {
        let cs = CString::new(artist).unwrap();
        let s = cs.as_ptr();
        unsafe {
            ll::taglib_tag_set_artist(self.raw, s);
        }
    }

    /// Returns the album name, or an empty string if no album name is present.
    pub fn album(&self) -> String {
        let res = unsafe { ll::taglib_tag_album(self.raw) };
        c_str_to_str(res)
    }

    /// Sets the album name.
    pub fn set_album(&mut self, album: &str) {
        let cs = CString::new(album).unwrap();
        let s = cs.as_ptr();
        unsafe {
            ll::taglib_tag_set_album(self.raw, s);
        }
    }

    /// Returns the track comment, or an empty string if no track comment is
    /// present.
    pub fn comment(&self) -> String {
        let res = unsafe { ll::taglib_tag_comment(self.raw) };
        c_str_to_str(res)
    }

    /// Sets the track comment.
    pub fn set_comment(&mut self, comment: &str) {
        let cs = CString::new(comment).unwrap();
        let s = cs.as_ptr();
        unsafe {
            ll::taglib_tag_set_comment(self.raw, s);
        }
    }

    /// Returns the genre name, or an empty string if no genre name is present.
    pub fn genre(&self) -> String {
        let res = unsafe { ll::taglib_tag_genre(self.raw) };
        c_str_to_str(res)
    }

    /// Sets the genre name.
    pub fn set_genre(&mut self, genre: &str) {
        let cs = CString::new(genre).unwrap();
        let s = cs.as_ptr();
        unsafe {
            ll::taglib_tag_set_genre(self.raw, s);
        }
    }

    /// Returns the year, or 0 if no year is present.
    pub fn year(&self) -> u32 {
        unsafe { ll::taglib_tag_year(self.raw) as u32 }
    }

    /// Sets the year.
    pub fn set_year(&mut self, year: u32) {
        unsafe {
            ll::taglib_tag_set_year(self.raw, year);
        }
    }

    /// Returns the track number, or 0 if no track number is present.
    pub fn track(&self) -> u32 {
        unsafe { ll::taglib_tag_track(self.raw) as u32 }
    }

    /// Sets the track number.
    pub fn set_track(&mut self, track: u32) {
        unsafe {
            ll::taglib_tag_set_track(self.raw, track);
        }
    }
}

impl<'a> AudioProperties<'a> {
    /// Returns the length, in seconds, of the track.
    pub fn length(&self) -> u32 {
        unsafe { ll::taglib_audioproperties_length(self.raw) as u32 }
    }

    /// Returns the most appropriate bit rate for the track, in kB/s.
    /// For constant bit rate formats, the returned value is the bit
    /// rate of the file; for variable bit rate formats this is either
    /// the average or the nominal bit rate.
    pub fn bitrate(&self) -> u32 {
        unsafe { ll::taglib_audioproperties_bitrate(self.raw) as u32 }
    }

    /// Returns the sample rate, in Hz.
    pub fn samplerate(&self) -> u32 {
        unsafe { ll::taglib_audioproperties_samplerate(self.raw) as u32 }
    }

    /// Returns the number of audio channels.
    pub fn channels(&self) -> u32 {
        unsafe { ll::taglib_audioproperties_channels(self.raw) as u32 }
    }
}

#[derive(Copy, Clone, PartialEq)]
pub enum FileType {
    /// MPEG file
    MPEG = ll::TAGLIB_FILE_MPEG as isize,
    /// Ogg/Vorbis file
    OggVorbis = ll::TAGLIB_FILE_OGG_VORBIS as isize,
    /// FLAC file
    FLAC = ll::TAGLIB_FILE_FLAC as isize,
    /// MPC file
    MPC = ll::TAGLIB_FILE_MPC as isize,
    /// Ogg/FLAC file
    OggFlac = ll::TAGLIB_FILE_OGG_FLAC as isize,
    /// WavPack file
    WavPack = ll::TAGLIB_FILE_WAV_PACK as isize,
    /// Ogg/Speex file
    Speex = ll::TAGLIB_FILE_SPEEX as isize,
    /// TrueAudio file
    TrueAudio = ll::TAGLIB_FILE_TRUE_AUDIO as isize,
    /// MP4 file
    MP4 = ll::TAGLIB_FILE_MP4 as isize,
    /// ASF file
    ASF = ll::TAGLIB_FILE_ASF as isize,
}

#[derive(Debug)]
pub enum FileError {
    /// The file is an invalid or an unrecognized audio container
    InvalidFile,
    /// The file name is invalid
    InvalidFileName,
    /// No meta-data is available
    NoAvailableTag,
    /// No audio properties are available
    NoAvailableAudioProperties,
}

impl Drop for File {
    fn drop(&mut self) {
        unsafe {
            ll::taglib_file_free(self.raw);
        }
    }
}

impl File {
    /// Creates a new `taglib::File` for the given `filename`.
    pub fn new(filename: &str) -> Result<File, FileError> {
        let filename_c = match CString::new(filename) {
            Ok(s) => s,
            _ => return Err(FileError::InvalidFileName),
        };

        let filename_c_ptr = filename_c.as_ptr();

        let f = unsafe { ll::taglib_file_new(filename_c_ptr) };
        if f.is_null() {
            return Err(FileError::InvalidFile);
        }

        Ok(File { raw: f })
    }

    /// Creates a new `taglib::File` for the given `filename` and type of file.
    pub fn new_type(filename: &str, filetype: FileType) -> Result<File, FileError> {
        let filename_c = match CString::new(filename) {
            Ok(s) => s,
            _ => return Err(FileError::InvalidFileName),
        };

        let filename_c_ptr = filename_c.as_ptr();
        let f = unsafe { ll::taglib_file_new_type(filename_c_ptr, filetype as u32) };
        if f.is_null() {
            return Err(FileError::InvalidFile);
        }

        Ok(File { raw: f })
    }

    /// Returns the `taglib::Tag` instance for the given file.
    pub fn tag(&self) -> Result<Tag, FileError> {
        let res = unsafe { ll::taglib_file_tag(self.raw) };

        if res.is_null() {
            Err(FileError::NoAvailableTag)
        } else {
            Ok(Tag {
                raw: res,
                file: self,
            })
        }
    }

    /// Returns whether the file is valid.
    pub fn is_valid(&self) -> bool {
        unsafe { ll::taglib_file_is_valid(self.raw) != 0 }
    }

    /// Returns the `taglib::AudioProperties` instance for the given file.
    pub fn audioproperties(&self) -> Result<AudioProperties, FileError> {
        let res = unsafe { ll::taglib_file_audioproperties(self.raw) };

        if res.is_null() {
            Err(FileError::NoAvailableAudioProperties)
        } else {
            Ok(AudioProperties {
                raw: res,
                file: self,
            })
        }
    }

    /// Updates the meta-data of the file.
    pub fn save(&self) -> bool {
        unsafe { ll::taglib_file_save(self.raw) != 0 }
    }
}

/// Fixture creation:
/// ffmpeg -t 0.01 -f s16le -i /dev/zero test.mp3
/// kid3-cli -c 'set artist "Artist"' test.mp3
#[cfg(test)]
mod test {
    const TEST_MP3: &'static str = "fixtures/test.mp3";

    use super::*;
    use std::fs;

    #[test]
    fn test_get_tag() {
        let file = File::new(TEST_MP3).unwrap();
        let tag = file.tag().unwrap();
        assert_eq!(tag.artist(), "Artist");
    }

    #[test]
    fn test_get_tag_explicit() {
        let file = File::new_type(TEST_MP3, FileType::MPEG).unwrap();
        let tag = file.tag().unwrap();
        assert_eq!(tag.artist(), "Artist");
    }

    #[test]
    fn test_get_audioproperties() {
        let file = File::new(TEST_MP3).unwrap();
        let ap = file.audioproperties().unwrap();
        assert_eq!(ap.length(), 0);
    }

    #[test]
    fn test_set_tag() {
        let temp_fn = "fixtures/temp.mp3";
        fs::copy(TEST_MP3, temp_fn).unwrap();
        let file = File::new(temp_fn).unwrap();
        let mut tag = file.tag().unwrap();

        tag.set_artist("Not Artist");
        file.save();

        assert_eq!(tag.artist(), "Not Artist");

        fs::remove_file(temp_fn).unwrap();
    }
}
<|endoftext|>


<commit_before>//! A library providing a generic connection pool.
#![feature(unsafe_destructor)]
#![warn(missing_doc)]
#![doc(html_root_url="http://www.rust-ci.org/sfackler/r2d2/doc")]

use std::sync::Mutex;
use std::fmt;

pub use config::Config;

mod config;

/// A trait which provides database-specific functionality.
pub trait PoolManager<C, E> {
    /// Attempts to create a new connection.
    fn connect(&self) -> Result<C, E>;

    /// Determines if the connection is still connected to the database.
    ///
    /// A standard implementation would check if a simple query like `SELECT 1`
    /// succeeds.
    fn is_valid(&self, conn: &C) -> bool;
}

/// An error type returned if pool creation fails.
#[deriving(PartialEq, Eq)]
pub enum NewPoolError<E> {
    /// The provided pool configuration was invalid.
    InvalidConfig(&'static str),
    /// The manager returned an error when creating a connection.
    ConnectionError(E),
}

impl<E: fmt::Show> fmt::Show for NewPoolError<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InvalidConfig(ref error) => write!(f, "Invalid config: {}", error),
            ConnectionError(ref error) => write!(f, "Unable to create connections: {}", error),
        }
    }
}

struct PoolInternals<C> {
    conns: Vec<C>,
    conn_count: uint,
}

/// A generic connection pool.
pub struct Pool<C, M> {
    config: Config,
    manager: M,
    internals: Mutex<PoolInternals<C>>,
}

impl<C: Send, E, M: PoolManager<C, E>> Pool<C, M> {
    /// Creates a new connection pool.
    pub fn new(config: Config, manager: M) -> Result<Pool<C, M>, NewPoolError<E>> {
        match config.validate() {
            Ok(()) => {}
            Err(err) => return Err(InvalidConfig(err))
        }

        let mut internals = PoolInternals {
            conns: vec![],
            conn_count: config.initial_size,
        };

        for _ in range(0, config.initial_size) {
            match manager.connect() {
                Ok(conn) => internals.conns.push(conn),
                Err(err) => return Err(ConnectionError(err)),
            }
        }

        Ok(Pool {
            config: config,
            manager: manager,
            internals: Mutex::new(internals),
        })
    }

    /// Retrieves a connection from the pool.
    pub fn get<'a>(&'a self) -> Result<PooledConnection<'a, C, M>, E> {
        let mut internals = self.internals.lock();

        loop {
            match internals.conns.pop() {
                Some(conn) => {
                    return Ok(PooledConnection {
                        pool: self,
                        conn: Some(conn)
                    })
                }
                None => internals.cond.wait(),
            }
        }
    }

    fn put_back(&self, conn: C) {
        let mut internals = self.internals.lock();
        internals.conns.push(conn);
        internals.cond.signal();
    }
}

/// A smart pointer wrapping an underlying connection.
///
/// ## Note
///
/// Due to Rust bug [#15905](https://github.com/rust-lang/rust/issues/15905),
/// the connection cannot be automatically returned to its pool when the
/// `PooledConnection` drops out of scope. The `replace` method must be called,
/// or the `PooledConnection`'s destructor `fail!()`.
pub struct PooledConnection<'a, C, M> {
    pool: &'a Pool<C, M>,
    conn: Option<C>,
}

impl<'a, C: Send, E, M: PoolManager<C, E>> PooledConnection<'a, C, M> {
    /// Consumes the `PooledConnection`, returning the connection to its pool.
    ///
    /// This must be called before the `PooledConnection` drops out of scope or
    /// its destructor will `fail!()`.
    pub fn replace(mut self) {
        self.pool.put_back(self.conn.take_unwrap())
    }
}

#[unsafe_destructor]
impl<'a, C, M> Drop for PooledConnection<'a, C, M> {
    fn drop(&mut self) {
        if self.conn.is_some() {
            fail!("You must call conn.replace()");
        }
    }
}

impl<'a, C, M> Deref<C> for PooledConnection<'a, C, M> {
    fn deref(&self) -> &C {
        self.conn.get_ref()
    }
}
<commit_msg>Doc typo<commit_after>//! A library providing a generic connection pool.
#![feature(unsafe_destructor)]
#![warn(missing_doc)]
#![doc(html_root_url="http://www.rust-ci.org/sfackler/r2d2/doc")]

use std::sync::Mutex;
use std::fmt;

pub use config::Config;

mod config;

/// A trait which provides database-specific functionality.
pub trait PoolManager<C, E> {
    /// Attempts to create a new connection.
    fn connect(&self) -> Result<C, E>;

    /// Determines if the connection is still connected to the database.
    ///
    /// A standard implementation would check if a simple query like `SELECT 1`
    /// succeeds.
    fn is_valid(&self, conn: &C) -> bool;
}

/// An error type returned if pool creation fails.
#[deriving(PartialEq, Eq)]
pub enum NewPoolError<E> {
    /// The provided pool configuration was invalid.
    InvalidConfig(&'static str),
    /// The manager returned an error when creating a connection.
    ConnectionError(E),
}

impl<E: fmt::Show> fmt::Show for NewPoolError<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InvalidConfig(ref error) => write!(f, "Invalid config: {}", error),
            ConnectionError(ref error) => write!(f, "Unable to create connections: {}", error),
        }
    }
}

struct PoolInternals<C> {
    conns: Vec<C>,
    conn_count: uint,
}

/// A generic connection pool.
pub struct Pool<C, M> {
    config: Config,
    manager: M,
    internals: Mutex<PoolInternals<C>>,
}

impl<C: Send, E, M: PoolManager<C, E>> Pool<C, M> {
    /// Creates a new connection pool.
    pub fn new(config: Config, manager: M) -> Result<Pool<C, M>, NewPoolError<E>> {
        match config.validate() {
            Ok(()) => {}
            Err(err) => return Err(InvalidConfig(err))
        }

        let mut internals = PoolInternals {
            conns: vec![],
            conn_count: config.initial_size,
        };

        for _ in range(0, config.initial_size) {
            match manager.connect() {
                Ok(conn) => internals.conns.push(conn),
                Err(err) => return Err(ConnectionError(err)),
            }
        }

        Ok(Pool {
            config: config,
            manager: manager,
            internals: Mutex::new(internals),
        })
    }

    /// Retrieves a connection from the pool.
    pub fn get<'a>(&'a self) -> Result<PooledConnection<'a, C, M>, E> {
        let mut internals = self.internals.lock();

        loop {
            match internals.conns.pop() {
                Some(conn) => {
                    return Ok(PooledConnection {
                        pool: self,
                        conn: Some(conn)
                    })
                }
                None => internals.cond.wait(),
            }
        }
    }

    fn put_back(&self, conn: C) {
        let mut internals = self.internals.lock();
        internals.conns.push(conn);
        internals.cond.signal();
    }
}

/// A smart pointer wrapping an underlying connection.
///
/// ## Note
///
/// Due to Rust bug [#15905](https://github.com/rust-lang/rust/issues/15905),
/// the connection cannot be automatically returned to its pool when the
/// `PooledConnection` drops out of scope. The `replace` method must be called,
/// or the `PooledConnection`'s destructor will `fail!()`.
pub struct PooledConnection<'a, C, M> {
    pool: &'a Pool<C, M>,
    conn: Option<C>,
}

impl<'a, C: Send, E, M: PoolManager<C, E>> PooledConnection<'a, C, M> {
    /// Consumes the `PooledConnection`, returning the connection to its pool.
    ///
    /// This must be called before the `PooledConnection` drops out of scope or
    /// its destructor will `fail!()`.
    pub fn replace(mut self) {
        self.pool.put_back(self.conn.take_unwrap())
    }
}

#[unsafe_destructor]
impl<'a, C, M> Drop for PooledConnection<'a, C, M> {
    fn drop(&mut self) {
        if self.conn.is_some() {
            fail!("You must call conn.replace()");
        }
    }
}

impl<'a, C, M> Deref<C> for PooledConnection<'a, C, M> {
    fn deref(&self) -> &C {
        self.conn.get_ref()
    }
}
<|endoftext|>