<commit_before>// Copyright (c) 2016 Anatoly Ikorsky
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

//! ## mysql-async
//! Tokio based asynchronous MySql client library for rust programming language.
//!
//! ### Installation
//! Library hosted on [crates.io](https://crates.io/crates/mysql_async/).
//!
//! ```toml
//! [dependencies]
//! mysql = "<desired version>"
//! ```
//!
//! ### Example
//!
//! ```rust
//! extern crate futures;
//! #[macro_use]
//! extern crate mysql_async as my;
//! extern crate tokio_core as tokio;
//! // ...
//!
//! use futures::Future;
//! use my::prelude::*;
//! use tokio::reactor::Core;
//! # use std::env;
//!
//! #[derive(Debug, PartialEq, Eq, Clone)]
//! struct Payment {
//!     customer_id: i32,
//!     amount: i32,
//!     account_name: Option<String>,
//! }
//!
//! fn main() {
//!     let mut lp = Core::new().unwrap();
//!
//!     let payments = vec![
//!         Payment { customer_id: 1, amount: 2, account_name: None },
//!         Payment { customer_id: 3, amount: 4, account_name: Some("foo".into()) },
//!         Payment { customer_id: 5, amount: 6, account_name: None },
//!         Payment { customer_id: 7, amount: 8, account_name: None },
//!         Payment { customer_id: 9, amount: 10, account_name: Some("bar".into()) },
//!     ];
//!
//!     # let database_url: String = if let Ok(url) = env::var("DATABASE_URL") {
//!     #     let opts = my::Opts::from_url(&url).expect("DATABASE_URL invalid");
//!     #     if opts.get_db_name().expect("a database name is required").is_empty() {
//!     #         panic!("database name is empty");
//!     #     }
//!     #     url
//!     # } else {
//!     #     "mysql://root:password@127.0.0.1:3307/mysql".into()
//!     # };
//!
//!     let pool = my::Pool::new(database_url, &lp.handle());
//!     let future = pool.get_conn().and_then(|conn| {
//!         // Create temporary table
//!         conn.drop_query(
//!             r"CREATE TEMPORARY TABLE payment (
//!                 customer_id int not null,
//!                 amount int not null,
//!                 account_name text
//!             )"
//!         )
//!     }).and_then(|conn| {
//!         // Save payments
//!         let params = payments.clone().into_iter().map(|payment| {
//!             params! {
//!                 "customer_id" => payment.customer_id,
//!                 "amount" => payment.amount,
//!                 "account_name" => payment.account_name.clone(),
//!             }
//!         });
//!
//!         conn.batch_exec(r"INSERT INTO payment (customer_id, amount, account_name)
//!                         VALUES (:customer_id, :amount, :account_name)", params)
//!     }).and_then(|conn| {
//!         // Load payments from database.
//!         conn.prep_exec("SELECT customer_id, amount, account_name FROM payment", ())
//!     }).and_then(|result| {
//!         // Collect payments
//!         result.map_and_drop(|row| {
//!             let (customer_id, amount, account_name) = my::from_row(row);
//!             Payment {
//!                 customer_id: customer_id,
//!                 amount: amount,
//!                 account_name: account_name,
//!             }
//!         })
//!     }).and_then(|(_ /* conn */, payments)| {
//!         // The destructor of a connection will return it to the pool,
//!         // but pool should be disconnected explicitly because it's
//!         // an asynchronous procedure.
//!         pool.disconnect().map(|_| payments)
//!     });
//!
//!     let loaded_payments = lp.run(future).unwrap();
//!
//!     assert_eq!(loaded_payments, payments);
//! }
//! ```

#![recursion_limit = "1024"]
#![cfg_attr(feature = "nightly", feature(test, const_fn, drop_types_in_const))]

#[cfg(feature = "nightly")]
extern crate test;

#[macro_use]
extern crate bitflags;
extern crate byteorder;
pub extern crate chrono;
#[macro_use]
extern crate error_chain;
extern crate fnv;
#[macro_use]
extern crate futures as lib_futures;
#[macro_use]
extern crate lazy_static;
extern crate mio;
extern crate regex;
extern crate serde;
extern crate serde_json;
extern crate sha1;
pub extern crate time;
extern crate tokio_core as tokio;
extern crate tokio_io;
extern crate twox_hash;
extern crate url;

#[macro_use]
pub mod macros;
#[macro_use]
mod value;
mod conn;
mod connection_like;
/// Mysql constants
pub mod consts;
/// Errors used in this crate
pub mod errors;
mod io;
mod local_infile_handler;
mod opts;
mod proto;
mod queryable;
mod scramble;

pub type BoxFuture<T> = Box<lib_futures::Future<Item = T, Error = errors::Error>>;

#[doc(inline)]
pub use self::conn::Conn;
#[doc(inline)]
pub use self::conn::pool::Pool;

#[doc(inline)]
pub use self::queryable::transaction::IsolationLevel;

#[doc(inline)]
pub use self::opts::{Opts, OptsBuilder};

#[doc(inline)]
pub use self::local_infile_handler::builtin::WhiteListFsLocalInfileHandler;

#[doc(inline)]
pub use self::proto::{Column, ErrPacket, Row};

#[doc(inline)]
pub use self::value::{from_row, from_row_opt, from_value, from_value_opt, Params, Value,
                      Serialized, Deserialized};

#[doc(inline)]
pub use self::queryable::query_result::QueryResult;

#[doc(inline)]
pub use self::queryable::transaction::{Transaction, TransactionOptions};

pub use self::queryable::{TextProtocol, BinaryProtocol};
pub use self::queryable::stmt::Stmt;

/// Futures used in this crate
mod futures {
    pub use queryable::query_result::{
        ForEachAndDrop,
        MapAndDrop,
        ReduceAndDrop,
        ForEach,
        Map,
        Reduce,
    };
}

/// Traits used in this crate
pub mod prelude {
    #[doc(inline)]
    pub use queryable::Queryable;
    #[doc(inline)]
    pub use local_infile_handler::LocalInfileHandler;
    #[doc(inline)]
    pub use value::ConvIr;
    #[doc(inline)]
    pub use value::FromRow;
    #[doc(inline)]
    pub use value::FromValue;
    #[doc(inline)]
    pub use value::ToValue;
}

#[cfg(test)]
mod test_misc {
    use std::env;
    use opts;
    lazy_static! {
        pub static ref DATABASE_URL: String = {
            if let Ok(url) = env::var("DATABASE_URL") {
                let opts = opts::Opts::from_url(&url).expect("DATABASE_URL invalid");
                if opts.get_db_name().expect("a database name is required").is_empty() {
                    panic!("database name is empty");
                }
                url
            } else {
                "mysql://root:password@127.0.0.1:3307/mysql".into()
            }
        };
    }
}
<commit_msg>Add #[doc(inline)] annotations to new reexports<commit_after>// Copyright (c) 2016 Anatoly Ikorsky
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

//! ## mysql-async
//! Tokio based asynchronous MySql client library for rust programming language.
//!
//! ### Installation
//! Library hosted on [crates.io](https://crates.io/crates/mysql_async/).
//!
//! ```toml
//! [dependencies]
//! mysql = "<desired version>"
//! ```
//!
//! ### Example
//!
//! ```rust
//! extern crate futures;
//! #[macro_use]
//! extern crate mysql_async as my;
//! extern crate tokio_core as tokio;
//! // ...
//!
//! use futures::Future;
//! use my::prelude::*;
//! use tokio::reactor::Core;
//! # use std::env;
//!
//! #[derive(Debug, PartialEq, Eq, Clone)]
//! struct Payment {
//!     customer_id: i32,
//!     amount: i32,
//!     account_name: Option<String>,
//! }
//!
//! fn main() {
//!     let mut lp = Core::new().unwrap();
//!
//!     let payments = vec![
//!         Payment { customer_id: 1, amount: 2, account_name: None },
//!         Payment { customer_id: 3, amount: 4, account_name: Some("foo".into()) },
//!         Payment { customer_id: 5, amount: 6, account_name: None },
//!         Payment { customer_id: 7, amount: 8, account_name: None },
//!         Payment { customer_id: 9, amount: 10, account_name: Some("bar".into()) },
//!     ];
//!
//!     # let database_url: String = if let Ok(url) = env::var("DATABASE_URL") {
//!     #     let opts = my::Opts::from_url(&url).expect("DATABASE_URL invalid");
//!     #     if opts.get_db_name().expect("a database name is required").is_empty() {
//!     #         panic!("database name is empty");
//!     #     }
//!     #     url
//!     # } else {
//!     #     "mysql://root:password@127.0.0.1:3307/mysql".into()
//!     # };
//!
//!     let pool = my::Pool::new(database_url, &lp.handle());
//!     let future = pool.get_conn().and_then(|conn| {
//!         // Create temporary table
//!         conn.drop_query(
//!             r"CREATE TEMPORARY TABLE payment (
//!                 customer_id int not null,
//!                 amount int not null,
//!                 account_name text
//!             )"
//!         )
//!     }).and_then(|conn| {
//!         // Save payments
//!         let params = payments.clone().into_iter().map(|payment| {
//!             params! {
//!                 "customer_id" => payment.customer_id,
//!                 "amount" => payment.amount,
//!                 "account_name" => payment.account_name.clone(),
//!             }
//!         });
//!
//!         conn.batch_exec(r"INSERT INTO payment (customer_id, amount, account_name)
//!                         VALUES (:customer_id, :amount, :account_name)", params)
//!     }).and_then(|conn| {
//!         // Load payments from database.
//!         conn.prep_exec("SELECT customer_id, amount, account_name FROM payment", ())
//!     }).and_then(|result| {
//!         // Collect payments
//!         result.map_and_drop(|row| {
//!             let (customer_id, amount, account_name) = my::from_row(row);
//!             Payment {
//!                 customer_id: customer_id,
//!                 amount: amount,
//!                 account_name: account_name,
//!             }
//!         })
//!     }).and_then(|(_ /* conn */, payments)| {
//!         // The destructor of a connection will return it to the pool,
//!         // but pool should be disconnected explicitly because it's
//!         // an asynchronous procedure.
//!         pool.disconnect().map(|_| payments)
//!     });
//!
//!     let loaded_payments = lp.run(future).unwrap();
//!
//!     assert_eq!(loaded_payments, payments);
//! }
//! ```

#![recursion_limit = "1024"]
#![cfg_attr(feature = "nightly", feature(test, const_fn, drop_types_in_const))]

#[cfg(feature = "nightly")]
extern crate test;

#[macro_use]
extern crate bitflags;
extern crate byteorder;
pub extern crate chrono;
#[macro_use]
extern crate error_chain;
extern crate fnv;
#[macro_use]
extern crate futures as lib_futures;
#[macro_use]
extern crate lazy_static;
extern crate mio;
extern crate regex;
extern crate serde;
extern crate serde_json;
extern crate sha1;
pub extern crate time;
extern crate tokio_core as tokio;
extern crate tokio_io;
extern crate twox_hash;
extern crate url;

#[macro_use]
pub mod macros;
#[macro_use]
mod value;
mod conn;
mod connection_like;
/// Mysql constants
pub mod consts;
/// Errors used in this crate
pub mod errors;
mod io;
mod local_infile_handler;
mod opts;
mod proto;
mod queryable;
mod scramble;

pub type BoxFuture<T> = Box<lib_futures::Future<Item = T, Error = errors::Error>>;

#[doc(inline)]
pub use self::conn::Conn;
#[doc(inline)]
pub use self::conn::pool::Pool;

#[doc(inline)]
pub use self::queryable::transaction::IsolationLevel;

#[doc(inline)]
pub use self::opts::{Opts, OptsBuilder};

#[doc(inline)]
pub use self::local_infile_handler::builtin::WhiteListFsLocalInfileHandler;

#[doc(inline)]
pub use self::proto::{Column, ErrPacket, Row};

#[doc(inline)]
pub use self::value::{from_row, from_row_opt, from_value, from_value_opt, Params, Value,
                      Serialized, Deserialized};

#[doc(inline)]
pub use self::queryable::query_result::QueryResult;

#[doc(inline)]
pub use self::queryable::transaction::{Transaction, TransactionOptions};

#[doc(inline)]
pub use self::queryable::{TextProtocol, BinaryProtocol};

#[doc(inline)]
pub use self::queryable::stmt::Stmt;

/// Futures used in this crate
mod futures {
    pub use queryable::query_result::{
        ForEachAndDrop,
        MapAndDrop,
        ReduceAndDrop,
        ForEach,
        Map,
        Reduce,
    };
}

/// Traits used in this crate
pub mod prelude {
    #[doc(inline)]
    pub use queryable::Queryable;
    #[doc(inline)]
    pub use local_infile_handler::LocalInfileHandler;
    #[doc(inline)]
    pub use value::ConvIr;
    #[doc(inline)]
    pub use value::FromRow;
    #[doc(inline)]
    pub use value::FromValue;
    #[doc(inline)]
    pub use value::ToValue;
}

#[cfg(test)]
mod test_misc {
    use std::env;
    use opts;
    lazy_static! {
        pub static ref DATABASE_URL: String = {
            if let Ok(url) = env::var("DATABASE_URL") {
                let opts = opts::Opts::from_url(&url).expect("DATABASE_URL invalid");
                if opts.get_db_name().expect("a database name is required").is_empty() {
                    panic!("database name is empty");
                }
                url
            } else {
                "mysql://root:password@127.0.0.1:3307/mysql".into()
            }
        };
    }
}
<|endoftext|>


<commit_before>use std::any::{TypeId, Any};
use std::clone::Clone;
use std::fmt::{Display, Debug, Formatter, Error as FmtError};

pub struct Variant<'a> {
   data: *mut (),
   vtable: &'a VTable<'a>,
}

impl<'a> Variant<'a> {
   pub fn new<T: Any>(value: T, vtable: &'a VTable<'a>) -> Self {
      Variant {
         data: Box::into_raw(Box::new(value)) as *mut (),
         vtable: vtable,
      }
   }

   #[inline]
   pub fn is<T: Any>(&self) -> bool {
      self.vtable.id == TypeId::of::<T>()
   }

   #[inline]
   pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
      if self.is::<T>() {
         unsafe { Some(&*(self.data as *const T)) }
      } else {
         None
      }
   }

   #[inline]
   pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
      if self.is::<T>() {
         unsafe { Some(&mut *(self.data as *mut T)) }
      } else {
         None
      }
   }

   #[inline]
   pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
      debug_assert!(self.is::<T>());

      &*(self.data as *const T)
   }

   #[inline]
   pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
      debug_assert!(self.is::<T>());

      &mut *(self.data as *mut T)
   }
}

impl<'a> Clone for Variant<'a> {
   fn clone(&self) -> Self {
      (self.vtable.clone)(self)
   }
}

impl<'a> Drop for Variant<'a> {
   fn drop(&mut self) {
      (self.vtable.drop)(self)
   }
}

impl<'a> Display for Variant<'a> {
   fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
      (self.vtable.display)(self, f)
   }
}

impl<'a> Debug for Variant<'a> {
   fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
      (self.vtable.debug)(self, f)
   }
}

type CloneFn<'a> = fn(&Variant<'a>) -> Variant<'a>;

type DropFn<'a> = fn(&mut Variant<'a>);

type DisplayFn<'a> = fn(&Variant<'a>, f: &mut Formatter) -> Result<(), FmtError>;

type DebugFn<'a> = DisplayFn<'a>;

pub struct VTable<'a> {
   id: TypeId,
   clone: CloneFn<'a>,
   drop: DropFn<'a>,
   display: DisplayFn<'a>,
   debug: DebugFn<'a>,
}

impl<'a> VTable<'a> {
   #[cfg_attr(feature = "cargo-clippy", allow(new_without_default))]
   pub fn new<T: Any + Clone + Display + Debug>() -> Self {
      VTable {
         id: TypeId::of::<T>(),
         clone: clone_variant::<T>,
         drop: drop_variant::<T>,
         display: display_variant::<T>,
         debug: debug_variant::<T>,
      }
   }

   pub fn variant<T: Any>(&'a self, value: T) -> Variant<'a> {
      Variant::new(value, self)
   }
}

fn clone_variant<'a, T: Any + Clone>(variant: &Variant<'a>) -> Variant<'a> {
   Variant::new(unsafe { variant.downcast_ref_unchecked() as &T }.clone(), variant.vtable)
}

fn drop_variant<T>(variant: &mut Variant) {
   drop(unsafe { *Box::from_raw(variant.data as *mut T) });
}

fn display_variant<T: Any + Display>(variant: &Variant, f: &mut Formatter) -> Result<(), FmtError> {
   Display::fmt(unsafe { variant.downcast_ref_unchecked() as &T }, f)
}

fn debug_variant<T: Any + Debug>(variant: &Variant, f: &mut Formatter) -> Result<(), FmtError> {
   Debug::fmt(unsafe { variant.downcast_ref_unchecked() as &T }, f)
}

#[cfg(test)]
mod tests {
   use std::fmt::{Display, Debug};

   use super::*;

   #[test]
   fn clone() {
      let vtable = VTable::new::<i64>();
      let origin = vtable.variant(1234_i64);
      let cloned = origin.clone();
      assert_eq!(origin.downcast_ref::<i64>(), cloned.downcast_ref::<i64>());
      assert_eq!(Some(&1234_i64), cloned.downcast_ref::<i64>());
   }

   #[test]
   fn drop_count() {
      #[derive(Clone, Debug)]
      struct Dropper(*mut usize);

      impl Drop for Dropper {
         fn drop(&mut self) {
            unsafe { *self.0 += 1 };
         }
      }

      impl Display for Dropper {
         fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
            Debug::fmt(self, f)
         }
      }

      let vtable = VTable::new::<Dropper>();
      let mut dropped: usize = 0;
      let variant = vtable.variant(Dropper(&mut dropped));
      drop(variant);
      assert_eq!(dropped, 1);

      dropped = 0;
      let variant = vtable.variant(Dropper(&mut dropped));
      let clone = variant.clone();
      drop(variant);
      drop(clone);
      assert_eq!(dropped, 2);
   }

   #[test]
   fn debug() {
      let vtable = VTable::new::<&str>();
      let variant = vtable.variant("data");
      assert_eq!("\"data\"", format!("{:?}", variant));

      let vtable = VTable::new::<i64>();
      let variant = vtable.variant(1234_i64);
      assert_eq!("1234", format!("{:?}", variant));
   }

   #[test]
   fn display() {
      let vtable = VTable::new::<&str>();
      let variant = vtable.variant("data");
      assert_eq!("data", format!("{}", variant));

      let vtable = VTable::new::<i64>();
      let variant = vtable.variant(1234_i64);
      assert_eq!("1234", format!("{}", variant));
   }
}
<commit_msg>VariantRef and VariantRefMut non-owning structs<commit_after>use std::any::{TypeId, Any};
use std::clone::Clone;
use std::fmt::{Display, Debug, Formatter, Error as FmtError};

pub struct Variant<'a> {
   data: *mut (),
   vtable: &'a VTable,
}

pub struct VariantRef<'a> {
   data: &'a (),
   vtable: &'a VTable,
}

pub struct VariantRefMut<'a> {
   data: &'a mut (),
   vtable: &'a VTable,
}

pub struct VTable {
   id: TypeId,
   clone: CloneFn,
   drop: DropFn,
   display: DisplayFn,
   debug: DebugFn,
}

type CloneFn = for<'b> fn(&Variant<'b>) -> Variant<'b>;

type DropFn = for<'b> fn(&mut Variant<'b>);

type DisplayFn = for<'b> fn(&Variant<'b>, f: &mut Formatter) -> Result<(), FmtError>;

type DebugFn = DisplayFn;

impl<'a> Variant<'a> {
   pub fn new<T: Any>(value: T, vtable: &'a VTable) -> Self {
      Variant {
         data: Box::into_raw(Box::new(value)) as *mut (),
         vtable: vtable,
      }
   }

   #[inline]
   pub fn is<T: Any>(&self) -> bool {
      self.vtable.id == TypeId::of::<T>()
   }

   #[inline]
   pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
      if self.is::<T>() {
         unsafe { Some(&*(self.data as *const T)) }
      } else {
         None
      }
   }

   #[inline]
   pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
      if self.is::<T>() {
         unsafe { Some(&mut *(self.data as *mut T)) }
      } else {
         None
      }
   }

   #[inline]
   pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
      debug_assert!(self.is::<T>());

      &*(self.data as *const T)
   }

   #[inline]
   pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
      debug_assert!(self.is::<T>());

      &mut *(self.data as *mut T)
   }
}

impl<'a> AsRef<VariantRef<'a>> for Variant<'a> {
   fn as_ref(&self) -> &VariantRef<'a> {
      unsafe { &*(self as *const _ as *const VariantRef<'a>) }
   }
}

impl<'a> AsMut<VariantRefMut<'a>> for Variant<'a> {
   fn as_mut(&mut self) -> &mut VariantRefMut<'a> {
      unsafe { &mut *(self as *mut _ as *mut VariantRefMut<'a>) }
   }
}

impl<'a> VariantRef<'a> {
   pub fn new<T: Any>(value: &'a T, vtable: &'a VTable) -> Self {
      VariantRef {
         data: unsafe { &*(value as *const _ as *const ()) },
         vtable: vtable,
      }
   }

   #[inline]
   pub fn is<T: Any>(&self) -> bool {
      self.vtable.id == TypeId::of::<T>()
   }

   #[inline]
   pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
      if self.is::<T>() {
         unsafe { Some(&*(self.data as *const _ as *const T)) }
      } else {
         None
      }
   }

   #[inline]
   pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
      debug_assert!(self.is::<T>());

      &*(self.data as *const _ as *const T)
   }
}

impl<'a> VariantRefMut<'a> {
   pub fn new<T: Any>(value: &'a mut T, vtable: &'a VTable) -> Self {
      VariantRefMut {
         data: unsafe { &mut *(value as *mut _ as *mut ()) },
         vtable: vtable,
      }
   }

   #[inline]
   pub fn is<T: Any>(&self) -> bool {
      self.vtable.id == TypeId::of::<T>()
   }

   #[inline]
   pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
      if self.is::<T>() {
         unsafe { Some(&*(self.data as *const _ as *const T)) }
      } else {
         None
      }
   }

   #[inline]
   pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
      if self.is::<T>() {
         unsafe { Some(&mut *(self.data as *mut _ as *mut T)) }
      } else {
         None
      }
   }

   #[inline]
   pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
      debug_assert!(self.is::<T>());

      &*(self.data as *const _ as *const T)
   }

   #[inline]
   pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
      debug_assert!(self.is::<T>());

      &mut *(self.data as *mut _ as *mut T)
   }
}

impl<'a> Clone for Variant<'a> {
   fn clone(&self) -> Self {
      (self.vtable.clone)(self)
   }
}

impl<'a> Drop for Variant<'a> {
   fn drop(&mut self) {
      (self.vtable.drop)(self)
   }
}

impl<'a> Display for Variant<'a> {
   fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
      (self.vtable.display)(self, f)
   }
}

impl<'a> Debug for Variant<'a> {
   fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
      (self.vtable.debug)(self, f)
   }
}

impl VTable {
   pub fn new<T: Any + Clone + Display + Debug>() -> Self {
      VTable {
         id: TypeId::of::<T>(),
         clone: clone_variant::<T>,
         drop: drop_variant::<T>,
         display: display_variant::<T>,
         debug: debug_variant::<T>,
      }
   }

   pub fn variant<T: Any>(&self, value: T) -> Variant {
      Variant::new(value, self)
   }

   pub fn variant_ref<'a, T: Any>(&'a self, value: &'a T) -> VariantRef<'a> {
      VariantRef::new(value, self)
   }

   pub fn variant_ref_mut<'a, T: Any>(&'a self, value: &'a mut T) -> VariantRefMut<'a> {
      VariantRefMut::new(value, self)
   }
}

fn clone_variant<'a, T: Any + Clone>(variant: &Variant<'a>) -> Variant<'a> {
   Variant::new(unsafe { variant.downcast_ref_unchecked() as &T }.clone(), variant.vtable)
}

fn drop_variant<T>(variant: &mut Variant) {
   drop(unsafe { *Box::from_raw(variant.data as *mut T) });
}

fn display_variant<T: Any + Display>(variant: &Variant, f: &mut Formatter) -> Result<(), FmtError> {
   Display::fmt(unsafe { variant.downcast_ref_unchecked() as &T }, f)
}

fn debug_variant<T: Any + Debug>(variant: &Variant, f: &mut Formatter) -> Result<(), FmtError> {
   Debug::fmt(unsafe { variant.downcast_ref_unchecked() as &T }, f)
}

#[cfg(test)]
mod tests {
   use std::fmt::{Display, Debug};

   use super::*;

   #[test]
   fn clone() {
      let vtable = VTable::new::<i64>();
      let origin = vtable.variant(1234_i64);
      let cloned = origin.clone();
      assert_eq!(origin.downcast_ref::<i64>(), cloned.downcast_ref::<i64>());
      assert_eq!(Some(&1234_i64), cloned.downcast_ref::<i64>());
   }

   #[test]
   fn drop_count() {
      #[derive(Clone, Debug)]
      struct Dropper(*mut usize);

      impl Drop for Dropper {
         fn drop(&mut self) {
            unsafe { *self.0 += 1 };
         }
      }

      impl Display for Dropper {
         fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
            Debug::fmt(self, f)
         }
      }

      let vtable = VTable::new::<Dropper>();
      let mut dropped: usize = 0;
      let variant = vtable.variant(Dropper(&mut dropped));
      drop(variant);
      assert_eq!(dropped, 1);

      dropped = 0;
      let variant = vtable.variant(Dropper(&mut dropped));
      let clone = variant.clone();
      drop(variant);
      drop(clone);
      assert_eq!(dropped, 2);
   }

   #[test]
   fn debug() {
      let vtable = VTable::new::<&str>();
      let variant = vtable.variant("data");
      assert_eq!("\"data\"", format!("{:?}", variant));

      let vtable = VTable::new::<i64>();
      let variant = vtable.variant(1234_i64);
      assert_eq!("1234", format!("{:?}", variant));
   }

   #[test]
   fn display() {
      let vtable = VTable::new::<&str>();
      let variant = vtable.variant("data");
      assert_eq!("data", format!("{}", variant));

      let vtable = VTable::new::<i64>();
      let variant = vtable.variant(1234_i64);
      assert_eq!("1234", format!("{}", variant));
   }

   #[test]
   fn as_ref() {
      let vtable = VTable::new::<i64>();
      let variant = vtable.variant(1234_i64);

      fn inner(variant: &VariantRef) {
         assert_eq!(Some(&1234_i64), variant.downcast_ref::<i64>());
      }

      inner(variant.as_ref());
   }

   #[test]
   fn as_mut() {
      let vtable = VTable::new::<i64>();
      let mut variant = vtable.variant(1234_i64);

      fn inner(variant: &mut VariantRefMut) {
         *variant.downcast_mut::<i64>().unwrap() *= 2;
      }

      inner(variant.as_mut());

      assert_eq!(Some(&2468_i64), variant.downcast_ref::<i64>());
   }

   #[test]
   fn stack_ref() {
      let vtable = VTable::new::<i64>();
      let values: [i64; 4] = [0, 2, 5, 6];
      let variants = [
         vtable.variant_ref(&values[0]),
         vtable.variant_ref(&values[1]),
         vtable.variant_ref(&values[2]),
         vtable.variant_ref(&values[3]),
      ];
      let mut sum: i64 = 0;
      for variant in &variants {
         sum += *variant.downcast_ref::<i64>().unwrap();
      }
      assert_eq!(13_i64, sum);
   }
}
<|endoftext|>


<commit_before>#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![doc(html_root_url = "https://docs.rs/pretty_env_logger/0.3.1")]

//! A logger configured via an environment variable which writes to standard
//! error with nice colored output for log levels.
//!
//! ## Example
//!
//! ```
//! extern crate pretty_env_logger;
//! #[macro_use] extern crate log;
//!
//! fn main() {
//!     pretty_env_logger::init();
//!
//!     trace!("a trace example");
//!     debug!("deboogging");
//!     info!("such information");
//!     warn!("o_O");
//!     error!("boom");
//! }
//! ```

extern crate env_logger;
extern crate log;
extern crate chrono;

use std::sync::atomic::{AtomicUsize, Ordering};

use chrono::Local;
use env_logger::{fmt::{Color, Style, StyledValue}, Builder};
use log::Level;

fn colored_level<'a>(style: &'a mut Style, level: Level) -> StyledValue<'a, &'static str> {
    match level {
        Level::Trace => style.set_color(Color::Magenta).value("TRACE"),
        Level::Debug => style.set_color(Color::Blue).value("DEBUG"),
        Level::Info => style.set_color(Color::Green).value("INFO "),
        Level::Warn => style.set_color(Color::Yellow).value("WARN "),
        Level::Error => style.set_color(Color::Red).value("ERROR"),
    }
}

static MAX_MODULE_WIDTH: AtomicUsize = AtomicUsize::new(0);

/// Initializes the global logger with a pretty env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Panics
///
/// This function fails to set the global logger if one has already been set.
#[inline]
pub fn init() {
    try_init().unwrap();
}

/// Initializes the global logger with a timed pretty env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Panics
///
/// This function fails to set the global logger if one has already been set.
#[inline]
pub fn init_timed() {
    try_init_timed().unwrap();
}

/// Initializes the global logger with a pretty env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Errors
///
/// This function fails to set the global logger if one has already been set.
pub fn try_init() -> Result<(), log::SetLoggerError> {
    try_init_custom_env("RUST_LOG")
}

/// Initializes the global logger with a timed pretty env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Errors
///
/// This function fails to set the global logger if one has already been set.
pub fn try_init_timed() -> Result<(), log::SetLoggerError> {
    try_init_timed_custom_env("RUST_LOG")
}

/// Initialized the global logger with a pretty env logger, with a custom variable name.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Panics
///
/// This function fails to set the global logger if one has already been set.
pub fn init_custom_env(environment_variable_name: &str) {
    try_init_custom_env(environment_variable_name).unwrap();
}

/// Initialized the global logger with a pretty env logger, with a custom variable name.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Errors
///
/// This function fails to set the global logger if one has already been set.
pub fn try_init_custom_env(environment_variable_name: &str) -> Result<(), log::SetLoggerError> {
    let mut builder = formatted_builder();

    if let Ok(s) = ::std::env::var(environment_variable_name) {
        builder.parse_filters(&s);
    }

    builder.try_init()
}

/// Initialized the global logger with a timed pretty env logger, with a custom variable name.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Errors
///
/// This function fails to set the global logger if one has already been set.
pub fn try_init_timed_custom_env(environment_variable_name: &str) -> Result<(), log::SetLoggerError> {
    let mut builder = formatted_timed_builder();

    if let Ok(s) = ::std::env::var(environment_variable_name) {
        builder.parse_filters(&s);
    }

    builder.try_init()
}

/// Returns a `env_logger::Builder` for further customization.
///
/// This method will return a colored and formatted `env_logger::Builder`
/// for further customization. Refer to env_logger::Build crate documentation
/// for further details and usage.
pub fn formatted_builder() -> Builder {
    let mut builder = Builder::new();

    builder.format(|f, record| {
        use std::io::Write;
        let target = record.target();
        let mut max_width = MAX_MODULE_WIDTH.load(Ordering::Relaxed);
        if max_width < target.len() {
            MAX_MODULE_WIDTH.store(target.len(), Ordering::Relaxed);
            max_width = target.len();
        }

        let mut style = f.style();
        let level = colored_level(&mut style, record.level());
        let mut style = f.style();
        let target = style.set_bold(true).value(format!("{: <width$}", target, width=max_width));
        writeln!(
            f,
            " {} {} > {}",
            level,
            target,
            record.args(),
        )
    });

    builder
}

/// Returns a `env_logger::Builder` for further customization.
///
/// This method will return a colored and time formatted `env_logger::Builder`
/// for further customization. Refer to env_logger::Build crate documentation
/// for further details and usage.
pub fn formatted_timed_builder() -> Builder {
    let mut builder = Builder::new();

    builder.format(|f, record| {
        use std::io::Write;
        let target = record.target();
        let mut max_width = MAX_MODULE_WIDTH.load(Ordering::Relaxed);
        if max_width < target.len() {
            MAX_MODULE_WIDTH.store(target.len(), Ordering::Relaxed);
            max_width = target.len();
        }

        let mut style = f.style();
        let level = colored_level(&mut style, record.level());
        let mut style = f.style();
        let target = style.set_bold(true).value(format!("{: <width$}", target, width=max_width));
        writeln!(
            f,
            " {} {} {} > {}",
            Local::now().format("%Y-%m-%dT%H:%M:%S%.3f"),
            level,
            target,
            record.args(),
        )
    });

    builder
}
<commit_msg>Make env_logger dependency public<commit_after>#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![doc(html_root_url = "https://docs.rs/pretty_env_logger/0.3.1")]

//! A logger configured via an environment variable which writes to standard
//! error with nice colored output for log levels.
//!
//! ## Example
//!
//! ```
//! extern crate pretty_env_logger;
//! #[macro_use] extern crate log;
//!
//! fn main() {
//!     pretty_env_logger::init();
//!
//!     trace!("a trace example");
//!     debug!("deboogging");
//!     info!("such information");
//!     warn!("o_O");
//!     error!("boom");
//! }
//! ```

pub extern crate env_logger;
extern crate log;
extern crate chrono;

use std::sync::atomic::{AtomicUsize, Ordering};

use chrono::Local;
use env_logger::{fmt::{Color, Style, StyledValue}, Builder};
use log::Level;

fn colored_level<'a>(style: &'a mut Style, level: Level) -> StyledValue<'a, &'static str> {
    match level {
        Level::Trace => style.set_color(Color::Magenta).value("TRACE"),
        Level::Debug => style.set_color(Color::Blue).value("DEBUG"),
        Level::Info => style.set_color(Color::Green).value("INFO "),
        Level::Warn => style.set_color(Color::Yellow).value("WARN "),
        Level::Error => style.set_color(Color::Red).value("ERROR"),
    }
}

static MAX_MODULE_WIDTH: AtomicUsize = AtomicUsize::new(0);

/// Initializes the global logger with a pretty env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Panics
///
/// This function fails to set the global logger if one has already been set.
#[inline]
pub fn init() {
    try_init().unwrap();
}

/// Initializes the global logger with a timed pretty env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Panics
///
/// This function fails to set the global logger if one has already been set.
#[inline]
pub fn init_timed() {
    try_init_timed().unwrap();
}

/// Initializes the global logger with a pretty env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Errors
///
/// This function fails to set the global logger if one has already been set.
pub fn try_init() -> Result<(), log::SetLoggerError> {
    try_init_custom_env("RUST_LOG")
}

/// Initializes the global logger with a timed pretty env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Errors
///
/// This function fails to set the global logger if one has already been set.
pub fn try_init_timed() -> Result<(), log::SetLoggerError> {
    try_init_timed_custom_env("RUST_LOG")
}

/// Initialized the global logger with a pretty env logger, with a custom variable name.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Panics
///
/// This function fails to set the global logger if one has already been set.
pub fn init_custom_env(environment_variable_name: &str) {
    try_init_custom_env(environment_variable_name).unwrap();
}

/// Initialized the global logger with a pretty env logger, with a custom variable name.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Errors
///
/// This function fails to set the global logger if one has already been set.
pub fn try_init_custom_env(environment_variable_name: &str) -> Result<(), log::SetLoggerError> {
    let mut builder = formatted_builder();

    if let Ok(s) = ::std::env::var(environment_variable_name) {
        builder.parse_filters(&s);
    }

    builder.try_init()
}

/// Initialized the global logger with a timed pretty env logger, with a custom variable name.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
///
/// # Errors
///
/// This function fails to set the global logger if one has already been set.
pub fn try_init_timed_custom_env(environment_variable_name: &str) -> Result<(), log::SetLoggerError> {
    let mut builder = formatted_timed_builder();

    if let Ok(s) = ::std::env::var(environment_variable_name) {
        builder.parse_filters(&s);
    }

    builder.try_init()
}

/// Returns a `env_logger::Builder` for further customization.
///
/// This method will return a colored and formatted `env_logger::Builder`
/// for further customization. Refer to env_logger::Build crate documentation
/// for further details and usage.
pub fn formatted_builder() -> Builder {
    let mut builder = Builder::new();

    builder.format(|f, record| {
        use std::io::Write;
        let target = record.target();
        let mut max_width = MAX_MODULE_WIDTH.load(Ordering::Relaxed);
        if max_width < target.len() {
            MAX_MODULE_WIDTH.store(target.len(), Ordering::Relaxed);
            max_width = target.len();
        }

        let mut style = f.style();
        let level = colored_level(&mut style, record.level());
        let mut style = f.style();
        let target = style.set_bold(true).value(format!("{: <width$}", target, width=max_width));
        writeln!(
            f,
            " {} {} > {}",
            level,
            target,
            record.args(),
        )
    });

    builder
}

/// Returns a `env_logger::Builder` for further customization.
///
/// This method will return a colored and time formatted `env_logger::Builder`
/// for further customization. Refer to env_logger::Build crate documentation
/// for further details and usage.
pub fn formatted_timed_builder() -> Builder {
    let mut builder = Builder::new();

    builder.format(|f, record| {
        use std::io::Write;
        let target = record.target();
        let mut max_width = MAX_MODULE_WIDTH.load(Ordering::Relaxed);
        if max_width < target.len() {
            MAX_MODULE_WIDTH.store(target.len(), Ordering::Relaxed);
            max_width = target.len();
        }

        let mut style = f.style();
        let level = colored_level(&mut style, record.level());
        let mut style = f.style();
        let target = style.set_bold(true).value(format!("{: <width$}", target, width=max_width));
        writeln!(
            f,
            " {} {} {} > {}",
            Local::now().format("%Y-%m-%dT%H:%M:%S%.3f"),
            level,
            target,
            record.args(),
        )
    });

    builder
}
<|endoftext|>


<commit_before>//! [![logo](http://i.imgur.com/dnpEXyh.jpg)](http://i.imgur.com/RUEw8EW.png)
//!
//! bspline
//! ===
//! A library for computing B-spline interpolating curves on generic control points. bspline can
//! be used to evaluate B-splines of varying orders on any type that can be linearly interpolated,
//! ranging from floats, positions, RGB colors to transformation matrices and so on.
//!
//! The bspline logo was generated using this library with a cubic B-spline in 2D for the positioning
//! of the curve and a quadratic B-spline in RGB space to color it (check out the
//! [logo](https://github.com/Twinklebear/bspline/blob/master/examples/logo.rs) example!). Other
//! much simpler examples of 1D and 2D quadratic, cubic and quartic B-splines can also be found in
//! the [examples](https://github.com/Twinklebear/bspline/tree/master/examples).
//!
//! # Readings on B-splines
//! The library assumes you are familiar at some level with how B-splines work, e.g. how
//! control points and knots and effect the curve produced. No interactive
//! editor is provided (at least currently). Some good places to start reading about B-splines to
//! effectively use this library can be found below.
//!
//! - [Wikipedia page on B-splines](https://en.wikipedia.org/wiki/B-spline)
//! - [Fundamentals of Computer Graphics](http://www.amazon.com/Fundamentals-Computer-Graphics-Peter-Shirley/dp/1568814690)
//! (has a good chapter on curves)
//! - [Splines and B-splines: An Introduction](http://www.uio.no/studier/emner/matnat/ifi/INF-MAT5340/v07/undervisningsmateriale/kap1.pdf)
//! - [Geometric Modeling](http://atrey.karlin.mff.cuni.cz/projekty/vrr/doc/grafika/geometric%20modelling.pdf)
//! - [A nice set of interactive examples](https://www.ibiblio.org/e-notes/Splines/Intro.htm)
//!

use std::ops::{Mul, Add};
use std::fmt::Debug;
use std::slice::Iter;

/// The interpolate trait is used to linearly interpolate between two types (or in the
/// case of Quaternions, spherically linearly interpolate). The B-spline curve uses this
/// trait to compute points on the curve for the given parameter value.
///
/// A default implementation of this trait is provided for all `T` that are `Mul<f32, Output = T>
/// + Add<Output = T> + Copy` since the interpolation provided by the trait is expected to be
/// a simple linear interpolation.
pub trait Interpolate {
    /// Linearly interpolate between `self` and `other` using `t`, for example with floats:
    ///
    /// ```text
    /// self * (1.0 - t) + other * t
    /// ```
    ///
    /// If the result returned is not a correct linear interpolation of the values the
    /// curve produced using the value may not be correct.
    fn interpolate(&self, other: &Self, t: f32) -> Self;
}

impl<T: Mul<f32, Output = T> + Add<Output = T> + Copy> Interpolate for T {
    fn interpolate(&self, other: &Self, t: f32) -> Self {
        *self * (1.0 - t) + *other * t
    }
}

/// Represents a B-spline that will use polynomials of the specified degree to interpolate
/// between the control points given the knots.
pub struct BSpline<T: Interpolate + Copy + Debug> {
    /// Degree of the polynomial that we use to make the curve segments
    degree: usize,
    /// Control points for the curve
    control_points: Vec<T>,
    /// The knot vector
    knots: Vec<f32>,
}

impl<T: Interpolate + Copy + Debug> BSpline<T> {
    /// Create a new B-spline curve of the desired `degree` that will interpolate
    /// the `control_points` using the `knots`. The knots should be sorted in non-decreasing
    /// order, otherwise they will be sorted for you which may lead to undesired knots
    /// for control points. Note that this is in terms of the interpolating polynomial degree,
    /// if you are familiar with the convention of "B-spline curve order" the degree is `curve_order - 1`.
    ///
    /// Your curve must have a valid number of control points and knots or the function will panic. A B-spline
    /// curve requires at least as many control points as the degree (`control_points.len() >=
    /// degree`) and the number of knots should be equal to `control_points.len() + degree + 1`.
    pub fn new(degree: usize, control_points: Vec<T>, mut knots: Vec<f32>) -> BSpline<T> {
        if control_points.len() < degree {
            panic!("Too few control points for curve");
        }
        if knots.len() != control_points.len() + degree + 1 {
            panic!(format!("Invalid number of knots, got {}, expected {}", knots.len(),
                control_points.len() + degree + 1));
        }
        knots.sort_by(|a, b| a.partial_cmp(b).unwrap());
        BSpline { degree: degree, control_points: control_points, knots: knots }
    }
    /// Compute a point on the curve at `t`, the parameter **must** be in the inclusive range
    /// of values returned by `knot_domain`. If `t` is out of bounds this function will assert
    /// on debug builds and on release builds you'll likely get an out of bounds crash.
    pub fn point(&self, t: f32) -> T {
        debug_assert!(t >= self.knot_domain().0 && t <= self.knot_domain().1);
        // Find the first index with a knot value greater than the t we're searching for. We want
        // to find i such that: knot[i] <= t < knot[i + 1]
        let i = match upper_bounds(&self.knots[..], t) {
            Some(x) if x == 0 => self.degree,
            Some(x) => x,
            None => self.knots.len() - self.degree - 1,
        };
        //self.de_boor(t, self.degree, i)
        self.de_boor_iterative(t, i)
    }
    /// Get an iterator over the control points.
    pub fn control_points(&self) -> Iter<T> {
        self.control_points.iter()
    }
    /// Get an iterator over the knots.
    pub fn knots(&self) -> Iter<f32> {
        self.knots.iter()
    }
    /// Get the min and max knot domain values for finding the `t` range to compute
    /// the curve over. The curve is only defined over this range, passing a `t` value
    /// out of this range will assert on debug builds and likely result in a crash on
    /// release builds.
    pub fn knot_domain(&self) -> (f32, f32) {
        (self.knots[self.degree], self.knots[self.knots.len() - 1 - self.degree])
    }
    /// Recursively compute de Boor's B-spline algorithm. TODO: This is not so good,
    /// compute it iteratively! Recursive version is just for a simple formualation
    /// of the initial implementation. Could we do memo-ization? If we switch to an
    /// iterative one and recursively compute the weights our interpolation at
    /// each level is no longer linear, which makes it harder to support things like
    /// Quaternions.
    fn de_boor(&self, t: f32, k: usize, i: usize) -> T {
        if k == 0 {
            self.control_points[i - 1]
        } else {
            let alpha = (t - self.knots[i - 1]) / (self.knots[i + self.degree - k] - self.knots[i - 1]);
            self.de_boor(t, k - 1, i - 1).interpolate(&self.de_boor(t, k - 1, i), alpha)
        }
    }
    fn de_boor_iterative(&self, t: f32, i_start: usize) -> T {
        let mut tmp = Vec::with_capacity(self.degree + 1);
        for j in 0..self.degree + 1 {
            let p = j + i_start - self.degree - 1;
            tmp.push(self.control_points[p]);
        }
        for lvl in 0..self.degree {
            let k = lvl + 1;
            for j in 0..self.degree - lvl {
                let i = j + k + i_start - self.degree;
                let alpha = (t - self.knots[i - 1]) / (self.knots[i + self.degree - k] - self.knots[i - 1]);
                tmp[j] = tmp[j].interpolate(&tmp[j + 1], alpha);
            }
        }
        tmp[0]
    }
}

/// Return the index of the first element greater than the value passed.
/// The data **must** be sorted.
/// If no element greater than the value passed is found the function returns None.
fn upper_bounds(data: &[f32], value: f32) -> Option<usize> {
    let mut first = 0usize;
    let mut step;
    let mut count = data.len() as isize;
    while count > 0 {
        step = count / 2;
        let it = first + step as usize;
        if !value.lt(&data[it]) {
            first = it + 1;
            count -= step + 1;
        } else {
            count = step;
        }
    }
    // If we didn't find an element greater than value
    if first == data.len() {
        None
    } else {
        Some(first)
    }
}

#[cfg(test)]
mod test {
    use std::ops::{Mul, Add};

    use super::BSpline;

    #[derive(Copy, Clone, Debug)]
    struct Point {
        x: f32,
        y: f32,
    }
    impl Point {
        fn new(x: f32, y: f32) -> Point {
            Point { x: x, y: y }
        }
    }
    impl Mul<f32> for Point {
        type Output = Point;
        fn mul(self, rhs: f32) -> Point {
            Point { x: self.x * rhs, y: self.y * rhs }
        }
    }
    impl Add for Point {
        type Output = Point;
        fn add(self, rhs: Point) -> Point {
            Point { x: self.x + rhs.x, y: self.y + rhs.y }
        }
    }

    // TODO: Test on 1D functions? Re-write tests
    #[test]
    fn linear_bspline() {
        let points = vec![Point::new(-1.0, 0.0), Point::new(0.0, 1.0),
                          Point::new(1.0, 1.0), Point::new(1.0, 2.0)];
        let knots = vec![0.0, 0.0, 1.0, 2.0, 3.0, 3.0];
        println!("Making spline, pts = {:?}\nknots = {:?}", points, knots);
        let spline = BSpline::new(1, points, knots);
        let x = spline.point(1.5);
        println!("spline(1.5) = {:?}", x);
        assert!(x.x == 0.5 && x.y == 1.0);
    }
}

<commit_msg>Remove recursive de Boor's update tests<commit_after>//! [![logo](http://i.imgur.com/dnpEXyh.jpg)](http://i.imgur.com/RUEw8EW.png)
//!
//! bspline
//! ===
//! A library for computing B-spline interpolating curves on generic control points. bspline can
//! be used to evaluate B-splines of varying orders on any type that can be linearly interpolated,
//! ranging from floats, positions, RGB colors to transformation matrices and so on.
//!
//! The bspline logo was generated using this library with a cubic B-spline in 2D for the positioning
//! of the curve and a quadratic B-spline in RGB space to color it (check out the
//! [logo](https://github.com/Twinklebear/bspline/blob/master/examples/logo.rs) example!). Other
//! much simpler examples of 1D and 2D quadratic, cubic and quartic B-splines can also be found in
//! the [examples](https://github.com/Twinklebear/bspline/tree/master/examples).
//!
//! # Readings on B-splines
//! The library assumes you are familiar at some level with how B-splines work, e.g. how
//! control points and knots and effect the curve produced. No interactive
//! editor is provided (at least currently). Some good places to start reading about B-splines to
//! effectively use this library can be found below.
//!
//! - [Wikipedia page on B-splines](https://en.wikipedia.org/wiki/B-spline)
//! - [Fundamentals of Computer Graphics](http://www.amazon.com/Fundamentals-Computer-Graphics-Peter-Shirley/dp/1568814690)
//! (has a good chapter on curves)
//! - [Splines and B-splines: An Introduction](http://www.uio.no/studier/emner/matnat/ifi/INF-MAT5340/v07/undervisningsmateriale/kap1.pdf)
//! - [Geometric Modeling](http://atrey.karlin.mff.cuni.cz/projekty/vrr/doc/grafika/geometric%20modelling.pdf)
//! - [A nice set of interactive examples](https://www.ibiblio.org/e-notes/Splines/Intro.htm)
//!

use std::ops::{Mul, Add};
use std::fmt::Debug;
use std::slice::Iter;

/// The interpolate trait is used to linearly interpolate between two types (or in the
/// case of Quaternions, spherically linearly interpolate). The B-spline curve uses this
/// trait to compute points on the curve for the given parameter value.
///
/// A default implementation of this trait is provided for all `T` that are `Mul<f32, Output = T>
/// + Add<Output = T> + Copy` since the interpolation provided by the trait is expected to be
/// a simple linear interpolation.
pub trait Interpolate {
    /// Linearly interpolate between `self` and `other` using `t`, for example with floats:
    ///
    /// ```text
    /// self * (1.0 - t) + other * t
    /// ```
    ///
    /// If the result returned is not a correct linear interpolation of the values the
    /// curve produced using the value may not be correct.
    fn interpolate(&self, other: &Self, t: f32) -> Self;
}

impl<T: Mul<f32, Output = T> + Add<Output = T> + Copy> Interpolate for T {
    fn interpolate(&self, other: &Self, t: f32) -> Self {
        *self * (1.0 - t) + *other * t
    }
}

/// Represents a B-spline that will use polynomials of the specified degree to interpolate
/// between the control points given the knots.
pub struct BSpline<T: Interpolate + Copy + Debug> {
    /// Degree of the polynomial that we use to make the curve segments
    degree: usize,
    /// Control points for the curve
    control_points: Vec<T>,
    /// The knot vector
    knots: Vec<f32>,
}

impl<T: Interpolate + Copy + Debug> BSpline<T> {
    /// Create a new B-spline curve of the desired `degree` that will interpolate
    /// the `control_points` using the `knots`. The knots should be sorted in non-decreasing
    /// order, otherwise they will be sorted for you which may lead to undesired knots
    /// for control points. Note that this is in terms of the interpolating polynomial degree,
    /// if you are familiar with the convention of "B-spline curve order" the degree is `curve_order - 1`.
    ///
    /// Your curve must have a valid number of control points and knots or the function will panic. A B-spline
    /// curve requires at least as many control points as the degree (`control_points.len() >=
    /// degree`) and the number of knots should be equal to `control_points.len() + degree + 1`.
    pub fn new(degree: usize, control_points: Vec<T>, mut knots: Vec<f32>) -> BSpline<T> {
        if control_points.len() < degree {
            panic!("Too few control points for curve");
        }
        if knots.len() != control_points.len() + degree + 1 {
            panic!(format!("Invalid number of knots, got {}, expected {}", knots.len(),
                control_points.len() + degree + 1));
        }
        knots.sort_by(|a, b| a.partial_cmp(b).unwrap());
        BSpline { degree: degree, control_points: control_points, knots: knots }
    }
    /// Compute a point on the curve at `t`, the parameter **must** be in the inclusive range
    /// of values returned by `knot_domain`. If `t` is out of bounds this function will assert
    /// on debug builds and on release builds you'll likely get an out of bounds crash.
    pub fn point(&self, t: f32) -> T {
        debug_assert!(t >= self.knot_domain().0 && t <= self.knot_domain().1);
        // Find the first index with a knot value greater than the t we're searching for. We want
        // to find i such that: knot[i] <= t < knot[i + 1]
        let i = match upper_bounds(&self.knots[..], t) {
            Some(x) if x == 0 => self.degree,
            Some(x) => x,
            None => self.knots.len() - self.degree - 1,
        };
        self.de_boor_iterative(t, i)
    }
    /// Get an iterator over the control points.
    pub fn control_points(&self) -> Iter<T> {
        self.control_points.iter()
    }
    /// Get an iterator over the knots.
    pub fn knots(&self) -> Iter<f32> {
        self.knots.iter()
    }
    /// Get the min and max knot domain values for finding the `t` range to compute
    /// the curve over. The curve is only defined over this (inclusive) range, passing
    /// a `t` value out of this range will assert on debug builds and likely result in
    /// a crash on release builds.
    pub fn knot_domain(&self) -> (f32, f32) {
        (self.knots[self.degree], self.knots[self.knots.len() - 1 - self.degree])
    }
    /// Iteratively compute de Boor's B-spline algorithm, this computes the recursive
    /// de Boor algorithm tree from the bottom up. At each level we use the results
    /// from the previous one to compute this level and store the results in the
    /// array indices we no longer need to compute the current level (the left one
    /// used computing node j).
    fn de_boor_iterative(&self, t: f32, i_start: usize) -> T {
        let mut tmp = Vec::with_capacity(self.degree + 1);
        for j in 0..self.degree + 1 {
            let p = j + i_start - self.degree - 1;
            tmp.push(self.control_points[p]);
        }
        for lvl in 0..self.degree {
            let k = lvl + 1;
            for j in 0..self.degree - lvl {
                let i = j + k + i_start - self.degree;
                let alpha = (t - self.knots[i - 1]) / (self.knots[i + self.degree - k] - self.knots[i - 1]);
                tmp[j] = tmp[j].interpolate(&tmp[j + 1], alpha);
            }
        }
        tmp[0]
    }
}

/// Return the index of the first element greater than the value passed.
/// The data **must** be sorted.
/// If no element greater than the value passed is found the function returns None.
fn upper_bounds(data: &[f32], value: f32) -> Option<usize> {
    let mut first = 0usize;
    let mut step;
    let mut count = data.len() as isize;
    while count > 0 {
        step = count / 2;
        let it = first + step as usize;
        if !value.lt(&data[it]) {
            first = it + 1;
            count -= step + 1;
        } else {
            count = step;
        }
    }
    // If we didn't find an element greater than value
    if first == data.len() {
        None
    } else {
        Some(first)
    }
}

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

    /// Check that the bspline returns the values we expect it to at various t values
    fn check_bspline(spline: &BSpline<f32>, expect: &Vec<(f32, f32)>) -> bool {
        expect.iter().fold(true, |ac, &(t, x)| ac && spline.point(t) == x)
    }

    #[test]
    fn linear_bspline() {
        let expect = vec![(0.0, 0.0), (0.2, 0.2), (0.4, 0.4), (0.6, 0.6),
                          (0.8, 0.8), (1.0, 1.0)];
        let points = vec![0.0, 1.0];
        let knots = vec![0.0, 0.0, 1.0, 1.0];
        let degree = 1;
        let spline = BSpline::new(degree, points, knots);
        assert!(check_bspline(&spline, &expect));
    }
    #[test]
    fn quadratic_bspline() {
        let expect = vec![(0.0, 0.0), (0.5, 0.125), (1.0, 0.5), (1.4, 0.74), (1.5, 0.75),
                          (1.6, 0.74), (2.0, 0.5), (2.5, 0.125), (3.0, 0.0)];
        let points = vec![0.0, 0.0, 1.0, 0.0, 0.0];
        let knots = vec![0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 3.0];
        let degree = 2;
        let spline = BSpline::new(degree, points, knots);
        assert!(check_bspline(&spline, &expect));
    }
    #[test]
    fn cubic_bspline() {
        let expect = vec![(-2.0, 0.0), (-1.5, 0.125), (-1.0, 1.0), (-0.6, 2.488),
                           (0.0, 4.0), (0.5, 2.875), (1.5, 0.12500001), (2.0, 0.0)];
        let points = vec![0.0, 0.0, 0.0, 6.0, 0.0, 0.0, 0.0];
        let knots = vec![-2.0, -2.0, -2.0, -2.0, -1.0, 0.0, 1.0, 2.0, 2.0, 2.0, 2.0];
        let degree = 3;
        let spline = BSpline::new(degree, points, knots);
        assert!(check_bspline(&spline, &expect));
    }
    #[test]
    fn quartic_bspline() {
        let expect = vec![(0.0, 0.0), (0.4, 0.0010666668), (1.0, 0.041666668),
                          (1.5, 0.19791667), (2.0, 0.4583333), (2.5, 0.5989583),
                          (3.0, 0.4583333), (3.2, 0.35206667), (4.1, 0.02733751),
                          (4.5, 0.002604167), (5.0, 0.0)];
        let points = vec![0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0];
        let knots = vec![0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 5.0, 5.0, 5.0, 5.0];
        let degree = 4;
        let spline = BSpline::new(degree, points, knots);
        assert!(check_bspline(&spline, &expect));
    }
}

<|endoftext|>


<commit_before>#![feature(question_mark)]

extern crate futures;
#[macro_use]
extern crate tokio_core;

pub mod buffered_io;
pub mod handshake;
<commit_msg>Remove unused compiler flag<commit_after>extern crate futures;
#[macro_use]
extern crate tokio_core;

pub mod buffered_io;
pub mod handshake;
<|endoftext|>


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

#![doc(html_root_url = "https://docs.rs/itoa/0.3.3")]

use std::{io, mem, ptr, slice};

#[inline]
pub fn write<W: io::Write, V: Integer>(wr: W, value: V) -> io::Result<usize> {
    value.write(wr)
}

pub trait Integer {
    fn write<W: io::Write>(self, W) -> io::Result<usize>;
}

trait IntegerPrivate {
    fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8];
}

const DEC_DIGITS_LUT: &'static[u8] =
    b"0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

const MAX_LEN: usize = 20;  // Tie between i64::MIN (including minus sign) and u64::MAX

// Adaptation of the original implementation at
// https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
macro_rules! impl_Integer {
    ($($t:ident),* as $conv_fn:ident) => ($(
    impl Integer for $t {
        fn write<W: io::Write>(self, mut wr: W) -> io::Result<usize> {
            let mut buf = unsafe { mem::uninitialized() };
            let bytes = self.write_to(&mut buf);
            try!(wr.write_all(bytes));
            Ok(bytes.len())
        }
    }

    impl IntegerPrivate for $t {
        #[allow(unused_comparisons)]
        fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8] {
            let is_nonnegative = self >= 0;
            let mut n = if is_nonnegative {
                self as $conv_fn
            } else {
                // convert the negative num to positive by summing 1 to it's 2 complement
                (!(self as $conv_fn)).wrapping_add(1)
            };
            let mut curr = buf.len() as isize;
            let buf_ptr = buf.as_mut_ptr();
            let lut_ptr = DEC_DIGITS_LUT.as_ptr();

            unsafe {
                // eagerly decode 4 characters at a time
                if <$t>::max_value() as u64 >= 10000 {
                    while n >= 10000 {
                        let rem = (n % 10000) as isize;
                        n /= 10000;

                        let d1 = (rem / 100) << 1;
                        let d2 = (rem % 100) << 1;
                        curr -= 4;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                        ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                    }
                }

                // if we reach here numbers are <= 9999, so at most 4 chars long
                let mut n = n as isize; // possibly reduce 64bit math

                // decode 2 more chars, if > 2 chars
                if n >= 100 {
                    let d1 = (n % 100) << 1;
                    n /= 100;
                    curr -= 2;
                    ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                }

                // decode last 1 or 2 chars
                if n < 10 {
                    curr -= 1;
                    *buf_ptr.offset(curr) = (n as u8) + 48;
                } else {
                    let d1 = n << 1;
                    curr -= 2;
                    ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                }

                if !is_nonnegative {
                    curr -= 1;
                    *buf_ptr.offset(curr) = b'-';
                }
            }

            let len = buf.len() - curr as usize;
            unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) }
        }
    })*);
}

impl_Integer!(i8, u8, i16, u16, i32, u32 as u32);
impl_Integer!(i64, u64 as u64);
#[cfg(target_pointer_width = "16")]
impl_Integer!(isize, usize as u16);
#[cfg(target_pointer_width = "32")]
impl_Integer!(isize, usize as u32);
#[cfg(target_pointer_width = "64")]
impl_Integer!(isize, usize as u64);
<commit_msg>Use a byte literal ASCII 0 instead of its decimal value.<commit_after>// Copyright 2016 Itoa Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![doc(html_root_url = "https://docs.rs/itoa/0.3.3")]

use std::{io, mem, ptr, slice};

#[inline]
pub fn write<W: io::Write, V: Integer>(wr: W, value: V) -> io::Result<usize> {
    value.write(wr)
}

pub trait Integer {
    fn write<W: io::Write>(self, W) -> io::Result<usize>;
}

trait IntegerPrivate {
    fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8];
}

const DEC_DIGITS_LUT: &'static[u8] =
    b"0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

const MAX_LEN: usize = 20;  // Tie between i64::MIN (including minus sign) and u64::MAX

// Adaptation of the original implementation at
// https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
macro_rules! impl_Integer {
    ($($t:ident),* as $conv_fn:ident) => ($(
    impl Integer for $t {
        fn write<W: io::Write>(self, mut wr: W) -> io::Result<usize> {
            let mut buf = unsafe { mem::uninitialized() };
            let bytes = self.write_to(&mut buf);
            try!(wr.write_all(bytes));
            Ok(bytes.len())
        }
    }

    impl IntegerPrivate for $t {
        #[allow(unused_comparisons)]
        fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8] {
            let is_nonnegative = self >= 0;
            let mut n = if is_nonnegative {
                self as $conv_fn
            } else {
                // convert the negative num to positive by summing 1 to it's 2 complement
                (!(self as $conv_fn)).wrapping_add(1)
            };
            let mut curr = buf.len() as isize;
            let buf_ptr = buf.as_mut_ptr();
            let lut_ptr = DEC_DIGITS_LUT.as_ptr();

            unsafe {
                // eagerly decode 4 characters at a time
                if <$t>::max_value() as u64 >= 10000 {
                    while n >= 10000 {
                        let rem = (n % 10000) as isize;
                        n /= 10000;

                        let d1 = (rem / 100) << 1;
                        let d2 = (rem % 100) << 1;
                        curr -= 4;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                        ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                    }
                }

                // if we reach here numbers are <= 9999, so at most 4 chars long
                let mut n = n as isize; // possibly reduce 64bit math

                // decode 2 more chars, if > 2 chars
                if n >= 100 {
                    let d1 = (n % 100) << 1;
                    n /= 100;
                    curr -= 2;
                    ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                }

                // decode last 1 or 2 chars
                if n < 10 {
                    curr -= 1;
                    *buf_ptr.offset(curr) = (n as u8) + b'0';
                } else {
                    let d1 = n << 1;
                    curr -= 2;
                    ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                }

                if !is_nonnegative {
                    curr -= 1;
                    *buf_ptr.offset(curr) = b'-';
                }
            }

            let len = buf.len() - curr as usize;
            unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) }
        }
    })*);
}

impl_Integer!(i8, u8, i16, u16, i32, u32 as u32);
impl_Integer!(i64, u64 as u64);
#[cfg(target_pointer_width = "16")]
impl_Integer!(isize, usize as u16);
#[cfg(target_pointer_width = "32")]
impl_Integer!(isize, usize as u32);
#[cfg(target_pointer_width = "64")]
impl_Integer!(isize, usize as u64);
<|endoftext|>


<commit_before>#![crate_type = "lib"]
#![feature(proc_macro)]
#![feature(plugin)]
#![feature(asm)]
#![plugin(bifrost_plugins)]
#![feature(conservative_impl_trait)]
#![feature(exact_size_is_empty)]

#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate bifrost;
extern crate bifrost_hasher;
#[macro_use]
extern crate dovahkiin;
#[macro_use]
extern crate serde_derive;

extern crate bincode;
extern crate serde;
extern crate parking_lot;
extern crate core;
extern crate rand;
extern crate futures;
extern crate linked_hash_map;
extern crate libc;
extern crate chashmap;

pub use dovahkiin;

pub mod utils;
#[macro_use]
pub mod ram;
pub mod server;
pub mod client;<commit_msg>expose inner dovahkiin lib<commit_after>#![crate_type = "lib"]
#![feature(proc_macro)]
#![feature(plugin)]
#![feature(asm)]
#![plugin(bifrost_plugins)]
#![feature(conservative_impl_trait)]
#![feature(exact_size_is_empty)]

#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate bifrost;
extern crate bifrost_hasher;
#[macro_use]
pub extern crate dovahkiin;
#[macro_use]
extern crate serde_derive;

extern crate bincode;
extern crate serde;
extern crate parking_lot;
extern crate core;
extern crate rand;
extern crate futures;
extern crate linked_hash_map;
extern crate libc;
extern crate chashmap;

pub mod utils;
#[macro_use]
pub mod ram;
pub mod server;
pub mod client;<|endoftext|>


<commit_before>extern crate libc;

pub mod ffi;
pub mod apr;
pub mod httpd;
pub mod wrapper;
pub mod cookie;

pub use libc::{c_void, c_char, c_int};

pub use httpd::{Request, Status, ProxyReq, CmdParms, server_banner, server_description,
   server_built, show_mpm};
pub use apr::{apr_version_string, apu_version_string, HookOrder, time_now};
pub use cookie::Cookie;

#[macro_export]
macro_rules! AP_DECLARE_MODULE {
   (
      $module:ident,
      $name:expr,
      $create_dir_config:expr,
      $merge_dir_config:expr,
      $create_server_config:expr,
      $merge_server_config:expr,
      $cmds:expr,
      $register_hooks:expr
   ) => {
      #[no_mangle]
      pub static mut $module: $crate::ffi::module = $crate::ffi::module {
         version: $crate::ffi::MODULE_MAGIC_NUMBER_MAJOR,
         minor_version: $crate::ffi::MODULE_MAGIC_NUMBER_MINOR,
         module_index: -1,
         name: $name as *const u8 as *const $crate::c_char,
         dynamic_load_handle: 0 as *mut $crate::c_void,
         next: 0 as *mut $crate::ffi::module,
         magic: $crate::ffi::MODULE_MAGIC_COOKIE,
         rewrite_args: None,
         create_dir_config: $create_dir_config,
         merge_dir_config: $merge_dir_config,
         create_server_config: $create_server_config,
         merge_server_config: $merge_server_config,
         cmds: unsafe { $cmds as *const $crate::ffi::command_rec },
         register_hooks: $register_hooks
      };
   }
}

#[macro_export]
macro_rules! apache2_module {
   ($handler:ident, $c_handler:ident, $module:ident, $c_name:expr) => {
      apache2_module!($handler, $c_handler, $module, $c_name, ap_hook_handler, $crate::HookOrder::MIDDLE);
   };

   ($handler:ident, $c_handler:ident, $module:ident, $c_name:expr, $hook:ident, $order:expr) => {
      AP_DECLARE_MODULE!(
         $module,
         $c_name,
         None,
         None,
         None,
         None,
         0,
         Some(c_module_hooks)
      );

      extern "C" fn c_module_hooks(_: *mut $crate::ffi::apr_pool_t) {
         unsafe {
            $crate::ffi::$hook(
               Some($c_handler),
               std::ptr::null(),
               std::ptr::null(),
               $order.into()
            );
         }
      }

      #[no_mangle]
      pub extern "C" fn $c_handler(r: *mut $crate::ffi::request_rec) -> $crate::c_int {
         match $crate::httpd::Request::from_raw_ptr(r) {
            Err(_) => $crate::httpd::Status::DECLINED.into(),
            Ok(mut request) => match $handler(&mut request) {
               Ok(status) => status,
               Err(_) => $crate::httpd::Status::HTTP_INTERNAL_SERVER_ERROR
            }.into()
         }
      }
   }
}

#[macro_export]
macro_rules! DECLARE_COMMAND_REC {
   (
      $name:expr,
      $func:expr,
      $cmd_data:expr,
      $req_override:expr,
      $args_how:expr,
      $errmsg:expr
   ) => {
      ffi::command_rec {
         name: $name as *const u8 as *const c_char,
         func: ffi::cmd_func {
            _bindgen_data_: [$func as u64]
         },
         cmd_data: $cmd_data as *mut c_void,
         req_override: $req_override,
         args_how: $args_how,
         errmsg: $errmsg as *const u8 as *const c_char
      }
   }
}

#[macro_export]
macro_rules! NULL_COMMAND_REC {
   () => {
      DECLARE_COMMAND_REC!(0, 0, 0, 0, 0, 0)
   }
}

#[macro_export]
macro_rules! AP_INIT_NO_ARGS {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::NO_ARGS, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_RAW_ARGS {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::RAW_ARGS, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_TAKE_ARGV {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::TAKE_ARGV, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_TAKE1 {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::TAKE1, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_ITERATE {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::ITERATE, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_TAKE2 {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::TAKE2, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_TAKE12 {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::TAKE12, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_ITERATE2 {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::ITERATE2, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_TAKE13 {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::TAKE13, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_TAKE23 {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::TAKE23, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_TAKE123 {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::TAKE123, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_TAKE3 {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::TAKE3, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_FLAG {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::FLAG, $errmsg)
   }
}

#[macro_export]
macro_rules! apache2_commands {
   ($cmds_name:ident, $cmd_count:expr, $( $cmd:expr ),*) => {
      #[no_mangle]
      pub static mut $cmds_name: [ffi::command_rec; $cmd_count] = [
         $(
            $cmd,
         )*
         NULL_COMMAND_REC!()
      ];
   };

   ($cmds_name:ident, $cmd1:expr) => {
      apache2_commands!($cmds_name, 2, $cmd1);
   };

   ($cmds_name:ident, $cmd1:expr, $cmd2:expr) => {
      apache2_commands!($cmds_name, 3, $cmd1, $cmd2);
   };

   ($cmds_name:ident, $cmd1:expr, $cmd2:expr, $cmd3:expr) => {
      apache2_commands!($cmds_name, 9, $cmd1, $cmd2, $cmd3);
   };

   ($cmds_name:ident, $cmd1:expr, $cmd2:expr, $cmd3:expr, $cmd4:expr) => {
      apache2_commands!($cmds_name, 9, $cmd1, $cmd2, $cmd3, $cmd4);
   };

   ($cmds_name:ident, $cmd1:expr, $cmd2:expr, $cmd3:expr, $cmd4:expr, $cmd5:expr) => {
      apache2_commands!($cmds_name, 9, $cmd1, $cmd2, $cmd3, $cmd4, $cmd5);
   };

   ($cmds_name:ident, $cmd1:expr, $cmd2:expr, $cmd3:expr, $cmd4:expr, $cmd5:expr, $cmd6:expr) => {
      apache2_commands!($cmds_name, 9, $cmd1, $cmd2, $cmd3, $cmd4, $cmd5, $cmd6);
   };

   ($cmds_name:ident, $cmd1:expr, $cmd2:expr, $cmd3:expr, $cmd4:expr, $cmd5:expr, $cmd6:expr, $cmd7:expr) => {
      apache2_commands!($cmds_name, 9, $cmd1, $cmd2, $cmd3, $cmd4, $cmd5, $cmd6, $cmd7);
   };

   ($cmds_name:ident, $cmd1:expr, $cmd2:expr, $cmd3:expr, $cmd4:expr, $cmd5:expr, $cmd6:expr, $cmd7:expr, $cmd8:expr) => {
      apache2_commands!($cmds_name, 9, $cmd1, $cmd2, $cmd3, $cmd4, $cmd5, $cmd6, $cmd7, $cmd8);
   };
}
<commit_msg>Supressing waring for unneeded unsafe usage.<commit_after>extern crate libc;

pub mod ffi;
pub mod apr;
pub mod httpd;
pub mod wrapper;
pub mod cookie;

pub use libc::{c_void, c_char, c_int};

pub use httpd::{Request, Status, ProxyReq, CmdParms, server_banner, server_description,
   server_built, show_mpm};
pub use apr::{apr_version_string, apu_version_string, HookOrder, time_now};
pub use cookie::Cookie;

#[macro_export]
macro_rules! AP_DECLARE_MODULE {
   (
      $module:ident,
      $name:expr,
      $create_dir_config:expr,
      $merge_dir_config:expr,
      $create_server_config:expr,
      $merge_server_config:expr,
      $cmds:expr,
      $register_hooks:expr
   ) => {
      #[allow(unused_unsafe)]
      #[no_mangle]
      pub static mut $module: $crate::ffi::module = $crate::ffi::module {
         version: $crate::ffi::MODULE_MAGIC_NUMBER_MAJOR,
         minor_version: $crate::ffi::MODULE_MAGIC_NUMBER_MINOR,
         module_index: -1,
         name: $name as *const u8 as *const $crate::c_char,
         dynamic_load_handle: 0 as *mut $crate::c_void,
         next: 0 as *mut $crate::ffi::module,
         magic: $crate::ffi::MODULE_MAGIC_COOKIE,
         rewrite_args: None,
         create_dir_config: $create_dir_config,
         merge_dir_config: $merge_dir_config,
         create_server_config: $create_server_config,
         merge_server_config: $merge_server_config,
         cmds: unsafe { $cmds as *const $crate::ffi::command_rec },
         register_hooks: $register_hooks
      };
   }
}

#[macro_export]
macro_rules! apache2_module {
   ($handler:ident, $c_handler:ident, $module:ident, $c_name:expr) => {
      apache2_module!($handler, $c_handler, $module, $c_name, ap_hook_handler, $crate::HookOrder::MIDDLE);
   };

   ($handler:ident, $c_handler:ident, $module:ident, $c_name:expr, $hook:ident, $order:expr) => {
      AP_DECLARE_MODULE!(
         $module,
         $c_name,
         None,
         None,
         None,
         None,
         0,
         Some(c_module_hooks)
      );

      extern "C" fn c_module_hooks(_: *mut $crate::ffi::apr_pool_t) {
         unsafe {
            $crate::ffi::$hook(
               Some($c_handler),
               std::ptr::null(),
               std::ptr::null(),
               $order.into()
            );
         }
      }

      #[no_mangle]
      pub extern "C" fn $c_handler(r: *mut $crate::ffi::request_rec) -> $crate::c_int {
         match $crate::httpd::Request::from_raw_ptr(r) {
            Err(_) => $crate::httpd::Status::DECLINED.into(),
            Ok(mut request) => match $handler(&mut request) {
               Ok(status) => status,
               Err(_) => $crate::httpd::Status::HTTP_INTERNAL_SERVER_ERROR
            }.into()
         }
      }
   }
}

#[macro_export]
macro_rules! DECLARE_COMMAND_REC {
   (
      $name:expr,
      $func:expr,
      $cmd_data:expr,
      $req_override:expr,
      $args_how:expr,
      $errmsg:expr
   ) => {
      ffi::command_rec {
         name: $name as *const u8 as *const c_char,
         func: ffi::cmd_func {
            _bindgen_data_: [$func as u64]
         },
         cmd_data: $cmd_data as *mut c_void,
         req_override: $req_override,
         args_how: $args_how,
         errmsg: $errmsg as *const u8 as *const c_char
      }
   }
}

#[macro_export]
macro_rules! NULL_COMMAND_REC {
   () => {
      DECLARE_COMMAND_REC!(0, 0, 0, 0, 0, 0)
   }
}

#[macro_export]
macro_rules! AP_INIT_NO_ARGS {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::NO_ARGS, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_RAW_ARGS {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::RAW_ARGS, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_TAKE_ARGV {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::TAKE_ARGV, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_TAKE1 {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::TAKE1, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_ITERATE {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::ITERATE, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_TAKE2 {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::TAKE2, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_TAKE12 {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::TAKE12, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_ITERATE2 {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::ITERATE2, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_TAKE13 {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::TAKE13, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_TAKE23 {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::TAKE23, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_TAKE123 {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::TAKE123, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_TAKE3 {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::TAKE3, $errmsg)
   }
}

#[macro_export]
macro_rules! AP_INIT_FLAG {
   ($name:expr, $func:expr, $req_override:expr, $errmsg:expr) => {
      DECLARE_COMMAND_REC!($name, $func, 0, $req_override, ffi::FLAG, $errmsg)
   }
}

#[macro_export]
macro_rules! apache2_commands {
   ($cmds_name:ident, $cmd_count:expr, $( $cmd:expr ),*) => {
      #[no_mangle]
      pub static mut $cmds_name: [ffi::command_rec; $cmd_count] = [
         $(
            $cmd,
         )*
         NULL_COMMAND_REC!()
      ];
   };

   ($cmds_name:ident, $cmd1:expr) => {
      apache2_commands!($cmds_name, 2, $cmd1);
   };

   ($cmds_name:ident, $cmd1:expr, $cmd2:expr) => {
      apache2_commands!($cmds_name, 3, $cmd1, $cmd2);
   };

   ($cmds_name:ident, $cmd1:expr, $cmd2:expr, $cmd3:expr) => {
      apache2_commands!($cmds_name, 9, $cmd1, $cmd2, $cmd3);
   };

   ($cmds_name:ident, $cmd1:expr, $cmd2:expr, $cmd3:expr, $cmd4:expr) => {
      apache2_commands!($cmds_name, 9, $cmd1, $cmd2, $cmd3, $cmd4);
   };

   ($cmds_name:ident, $cmd1:expr, $cmd2:expr, $cmd3:expr, $cmd4:expr, $cmd5:expr) => {
      apache2_commands!($cmds_name, 9, $cmd1, $cmd2, $cmd3, $cmd4, $cmd5);
   };

   ($cmds_name:ident, $cmd1:expr, $cmd2:expr, $cmd3:expr, $cmd4:expr, $cmd5:expr, $cmd6:expr) => {
      apache2_commands!($cmds_name, 9, $cmd1, $cmd2, $cmd3, $cmd4, $cmd5, $cmd6);
   };

   ($cmds_name:ident, $cmd1:expr, $cmd2:expr, $cmd3:expr, $cmd4:expr, $cmd5:expr, $cmd6:expr, $cmd7:expr) => {
      apache2_commands!($cmds_name, 9, $cmd1, $cmd2, $cmd3, $cmd4, $cmd5, $cmd6, $cmd7);
   };

   ($cmds_name:ident, $cmd1:expr, $cmd2:expr, $cmd3:expr, $cmd4:expr, $cmd5:expr, $cmd6:expr, $cmd7:expr, $cmd8:expr) => {
      apache2_commands!($cmds_name, 9, $cmd1, $cmd2, $cmd3, $cmd4, $cmd5, $cmd6, $cmd7, $cmd8);
   };
}
<|endoftext|>