<commit_before>//! ByteSize is an utility that easily makes bytes size representation
//! and helps its arithmetic operations.
//!
//! ## Example
//!
//! ```ignore
//! extern crate bytesize;
//!
//! use bytesize::ByteSize;
//!
//! fn byte_arithmetic_operator() {
//!   let x = ByteSize::mb(1);
//!   let y = ByteSize::kb(100);
//!
//!   let plus = x + y;
//!   print!("{} bytes", plus.as_u64());
//!
//!   let minus = ByteSize::tb(100) - ByteSize::gb(4);
//!   print!("{} bytes", minus.as_u64());
//! }
//! ```
//!
//! It also provides its human readable string as follows:
//!
//! ```ignore=
//!  assert_eq!("482 GiB".to_string(), ByteSize::gb(518).to_string(true));
//!  assert_eq!("518 GB".to_string(), ByteSize::gb(518).to_string(false));
//! ```

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

use std::fmt::{Debug, Display, Formatter, Result};
use std::ops::{Add, Mul};

/// byte size for 1 byte
pub const B: u64 = 1;
/// bytes size for 1 kilobyte
pub const KB: u64 = 1_000;
/// bytes size for 1 megabyte
pub const MB: u64 = 1_000_000;
/// bytes size for 1 gigabyte
pub const GB: u64 = 1_000_000_000;
/// bytes size for 1 terabyte
pub const TB: u64 = 1_000_000_000_000;
/// bytes size for 1 petabyte
pub const PB: u64 = 1_000_000_000_000_000;

/// bytes size for 1 kibibyte
pub const KIB: u64 = 1_024;
/// bytes size for 1 mebibyte
pub const MIB: u64 = 1_048_576;
/// bytes size for 1 gibibyte
pub const GIB: u64 = 1_073_741_824;
/// bytes size for 1 tebibyte
pub const TIB: u64 = 1_099_511_627_776;
/// bytes size for 1 pebibyte
pub const PIB: u64 = 1_125_899_906_842_624;

static UNITS: &'static str = "KMGTPE";
static UNITS_SI: &'static str = "kMGTPE";
static LN_KB: f64 = 6.931471806; // ln 1024
static LN_KIB: f64 = 6.907755279; // ln 1000

pub fn kb<V: Into<u64>>(size: V) -> u64 {
    size.into() * KB
}

pub fn kib<V: Into<u64>>(size: V) -> u64 {
    size.into() * KIB
}

pub fn mb<V: Into<u64>>(size: V) -> u64 {
    size.into() * MB
}

pub fn mib<V: Into<u64>>(size: V) -> u64 {
    size.into() * MIB
}

pub fn gb<V: Into<u64>>(size: V) -> u64 {
    size.into() * GB
}

pub fn gib<V: Into<u64>>(size: V) -> u64 {
    size.into() * GIB
}

pub fn tb<V: Into<u64>>(size: V) -> u64 {
    size.into() * TB
}

pub fn tib<V: Into<u64>>(size: V) -> u64 {
    size.into() * TIB
}

pub fn pb<V: Into<u64>>(size: V) -> u64 {
    size.into() * PB
}

pub fn pib<V: Into<u64>>(size: V) -> u64 {
    size.into() * PIB
}

/// Byte size representation
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ByteSize(pub u64);

impl ByteSize {
    #[inline(always)]
    pub fn b(size: u64) -> ByteSize {
        ByteSize(size)
    }

    #[inline(always)]
    pub fn kb(size: u64) -> ByteSize {
        ByteSize(size * KB)
    }

    #[inline(always)]
    pub fn kib(size: u64) -> ByteSize {
        ByteSize(size * KIB)
    }

    #[inline(always)]
    pub fn mb(size: u64) -> ByteSize {
        ByteSize(size * MB)
    }

    #[inline(always)]
    pub fn mib(size: u64) -> ByteSize {
        ByteSize(size * MIB)
    }

    #[inline(always)]
    pub fn gb(size: u64) -> ByteSize {
        ByteSize(size * GB)
    }

    #[inline(always)]
    pub fn gib(size: u64) -> ByteSize {
        ByteSize(size * GIB)
    }

    #[inline(always)]
    pub fn tb(size: u64) -> ByteSize {
        ByteSize(size * TB)
    }

    #[inline(always)]
    pub fn tib(size: u64) -> ByteSize {
        ByteSize(size * TIB)
    }

    #[inline(always)]
    pub fn pb(size: u64) -> ByteSize {
        ByteSize(size * PB)
    }

    #[inline(always)]
    pub fn pib(size: u64) -> ByteSize {
        ByteSize(size * PIB)
    }

    #[inline(always)]
    pub fn as_u64(&self) -> u64 {
        self.0
    }

    #[inline(always)]
    pub fn to_string_as(&self, si_unit: bool) -> String {
        to_string(self.0, si_unit)
    }
}

pub fn to_string(bytes: u64, si_prefix: bool) -> String {
    let unit = if si_prefix { KIB } else { KB };
    let unit_base = if si_prefix { LN_KIB } else { LN_KB };
    let unit_prefix = if si_prefix {
        UNITS_SI.as_bytes()
    } else {
        UNITS.as_bytes()
    };
    let unit_suffix = if si_prefix { "iB" } else { "B" };

    if bytes < unit {
        format!("{} B", bytes)
    } else {
        let size = bytes as f64;
        let exp = match (size.ln() / unit_base) as usize {
            e if e == 0 => 1,
            e => e,
        };

        format!(
            "{:.1} {}{}",
            (size / unit.pow(exp as u32) as f64),
            unit_prefix[exp - 1] as char,
            unit_suffix
        )
    }
}

impl Display for ByteSize {
    fn fmt(&self, f: &mut Formatter) -> Result {
        f.pad(&to_string(self.0, false))
    }
}

impl Debug for ByteSize {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}", self)
    }
}

macro_rules! commutative_op {
    ($t:ty) => {
        impl Add<$t> for ByteSize {
            type Output = ByteSize;
            #[inline(always)]
            fn add(self, rhs: $t) -> ByteSize {
                ByteSize(self.0 + (rhs as u64))
            }
        }

        impl Add<ByteSize> for $t {
            type Output = ByteSize;
            #[inline(always)]
            fn add(self, rhs: ByteSize) -> ByteSize {
                ByteSize(rhs.0 + (self as u64))
            }
        }

        impl Mul<$t> for ByteSize {
            type Output = ByteSize;
            #[inline(always)]
            fn mul(self, rhs: $t) -> ByteSize {
                ByteSize(self.0 * (rhs as u64))
            }
        }

        impl Mul<ByteSize> for $t {
            type Output = ByteSize;
            #[inline(always)]
            fn mul(self, rhs: ByteSize) -> ByteSize {
                ByteSize(rhs.0 * (self as u64))
            }
        }
    };
}

commutative_op!(u64);
commutative_op!(u32);
commutative_op!(u16);
commutative_op!(u8);

impl Add<ByteSize> for ByteSize {
    type Output = ByteSize;

    #[inline(always)]
    fn add(self, rhs: ByteSize) -> ByteSize {
        ByteSize(self.0 + rhs.0)
    }
}

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

    #[test]
    fn test_arithmetic_op() {
        let x = ByteSize::mb(1);
        let y = ByteSize::kb(100);

        assert_eq!((x + y).as_u64(), 1_100_000u64);

        assert_eq!((x + (100 * 1000) as u64).as_u64(), 1_100_000);

        assert_eq!((x * 2u64).as_u64(), 2_000_000);
    }

    #[test]
    fn test_arithmetic_primitives() {
        let x = ByteSize::mb(1);

        assert_eq!((x + MB as u64).as_u64(), 2_000_000);

        assert_eq!((x + MB as u32).as_u64(), 2_000_000);

        assert_eq!((x + KB as u16).as_u64(), 1_001_000);

        assert_eq!((x + B as u8).as_u64(), 1_000_001);
    }

    #[test]
    fn test_comparison() {
        assert!(ByteSize::mb(1) == ByteSize::kb(1000));
        assert!(ByteSize::mib(1) == ByteSize::kib(1024));
        assert!(ByteSize::mb(1) != ByteSize::kib(1024));
        assert!(ByteSize::mb(1) < ByteSize::kib(1024));
        assert!(ByteSize::b(0) < ByteSize::tib(1));
    }

    fn assert_display(expected: &str, b: ByteSize) {
        assert_eq!(expected, format!("{}", b));
    }

    #[test]
    fn test_display() {
        assert_display("215 B", ByteSize::b(215));
        assert_display("1.0 KB", ByteSize::kb(1));
        assert_display("301.0 KB", ByteSize::kb(301));
        assert_display("419.0 MB", ByteSize::mb(419));
        assert_display("518.0 GB", ByteSize::gb(518));
        assert_display("815.0 TB", ByteSize::tb(815));
        assert_display("609.0 PB", ByteSize::pb(609));
    }

    #[test]
    fn test_display_alignment() {
        assert_eq!("|357 B     |", format!("|{:10}|", ByteSize(357)));
        assert_eq!("|     357 B|", format!("|{:>10}|", ByteSize(357)));
        assert_eq!("|357 B     |", format!("|{:<10}|", ByteSize(357)));
        assert_eq!("|  357 B   |", format!("|{:^10}|", ByteSize(357)));

        assert_eq!("|-----357 B|", format!("|{:->10}|", ByteSize(357)));
        assert_eq!("|357 B-----|", format!("|{:-<10}|", ByteSize(357)));
        assert_eq!("|--357 B---|", format!("|{:-^10}|", ByteSize(357)));
    }

    fn assert_to_string(expected: &str, b: ByteSize, si: bool) {
        assert_eq!(expected.to_string(), b.to_string_as(si));
    }

    #[test]
    fn test_to_string_as() {
        assert_to_string("215 B", ByteSize::b(215), true);
        assert_to_string("215 B", ByteSize::b(215), false);

        assert_to_string("1.0 kiB", ByteSize::kib(1), true);
        assert_to_string("1.0 KB", ByteSize::kib(1), false);

        assert_to_string("293.9 kiB", ByteSize::kb(301), true);
        assert_to_string("301.0 KB", ByteSize::kb(301), false);

        assert_to_string("1.0 MiB", ByteSize::mib(1), true);
        assert_to_string("1048.6 KB", ByteSize::mib(1), false);

        // a bug case: https://github.com/flang-project/bytesize/issues/8
        assert_to_string("1.9 GiB", ByteSize::mib(1907), true);
        assert_to_string("2.0 GB", ByteSize::mib(1908), false);

        assert_to_string("399.6 MiB", ByteSize::mb(419), true);
        assert_to_string("419.0 MB", ByteSize::mb(419), false);

        assert_to_string("482.4 GiB", ByteSize::gb(518), true);
        assert_to_string("518.0 GB", ByteSize::gb(518), false);

        assert_to_string("741.2 TiB", ByteSize::tb(815), true);
        assert_to_string("815.0 TB", ByteSize::tb(815), false);

        assert_to_string("540.9 PiB", ByteSize::pb(609), true);
        assert_to_string("609.0 PB", ByteSize::pb(609), false);
    }

    #[test]
    fn test_default() {
        assert_eq!(ByteSize::b(0), ByteSize::default());
    }

    #[test]
    fn test_to_string() {
        assert_to_string("609.0 PB", ByteSize::pb(609), false);
    }
}
<commit_msg>It will be great if we allow creating ByteSize constants<commit_after>//! ByteSize is an utility that easily makes bytes size representation
//! and helps its arithmetic operations.
//!
//! ## Example
//!
//! ```ignore
//! extern crate bytesize;
//!
//! use bytesize::ByteSize;
//!
//! fn byte_arithmetic_operator() {
//!   let x = ByteSize::mb(1);
//!   let y = ByteSize::kb(100);
//!
//!   let plus = x + y;
//!   print!("{} bytes", plus.as_u64());
//!
//!   let minus = ByteSize::tb(100) - ByteSize::gb(4);
//!   print!("{} bytes", minus.as_u64());
//! }
//! ```
//!
//! It also provides its human readable string as follows:
//!
//! ```ignore=
//!  assert_eq!("482 GiB".to_string(), ByteSize::gb(518).to_string(true));
//!  assert_eq!("518 GB".to_string(), ByteSize::gb(518).to_string(false));
//! ```

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

use std::fmt::{Debug, Display, Formatter, Result};
use std::ops::{Add, Mul};

/// byte size for 1 byte
pub const B: u64 = 1;
/// bytes size for 1 kilobyte
pub const KB: u64 = 1_000;
/// bytes size for 1 megabyte
pub const MB: u64 = 1_000_000;
/// bytes size for 1 gigabyte
pub const GB: u64 = 1_000_000_000;
/// bytes size for 1 terabyte
pub const TB: u64 = 1_000_000_000_000;
/// bytes size for 1 petabyte
pub const PB: u64 = 1_000_000_000_000_000;

/// bytes size for 1 kibibyte
pub const KIB: u64 = 1_024;
/// bytes size for 1 mebibyte
pub const MIB: u64 = 1_048_576;
/// bytes size for 1 gibibyte
pub const GIB: u64 = 1_073_741_824;
/// bytes size for 1 tebibyte
pub const TIB: u64 = 1_099_511_627_776;
/// bytes size for 1 pebibyte
pub const PIB: u64 = 1_125_899_906_842_624;

static UNITS: &'static str = "KMGTPE";
static UNITS_SI: &'static str = "kMGTPE";
static LN_KB: f64 = 6.931471806; // ln 1024
static LN_KIB: f64 = 6.907755279; // ln 1000

pub fn kb<V: Into<u64>>(size: V) -> u64 {
    size.into() * KB
}

pub fn kib<V: Into<u64>>(size: V) -> u64 {
    size.into() * KIB
}

pub fn mb<V: Into<u64>>(size: V) -> u64 {
    size.into() * MB
}

pub fn mib<V: Into<u64>>(size: V) -> u64 {
    size.into() * MIB
}

pub fn gb<V: Into<u64>>(size: V) -> u64 {
    size.into() * GB
}

pub fn gib<V: Into<u64>>(size: V) -> u64 {
    size.into() * GIB
}

pub fn tb<V: Into<u64>>(size: V) -> u64 {
    size.into() * TB
}

pub fn tib<V: Into<u64>>(size: V) -> u64 {
    size.into() * TIB
}

pub fn pb<V: Into<u64>>(size: V) -> u64 {
    size.into() * PB
}

pub fn pib<V: Into<u64>>(size: V) -> u64 {
    size.into() * PIB
}

/// Byte size representation
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ByteSize(pub u64);

impl ByteSize {
    #[inline(always)]
    pub const fn b(size: u64) -> ByteSize {
        ByteSize(size)
    }

    #[inline(always)]
    pub const fn kb(size: u64) -> ByteSize {
        ByteSize(size * KB)
    }

    #[inline(always)]
    pub const fn kib(size: u64) -> ByteSize {
        ByteSize(size * KIB)
    }

    #[inline(always)]
    pub const fn mb(size: u64) -> ByteSize {
        ByteSize(size * MB)
    }

    #[inline(always)]
    pub const fn mib(size: u64) -> ByteSize {
        ByteSize(size * MIB)
    }

    #[inline(always)]
    pub const fn gb(size: u64) -> ByteSize {
        ByteSize(size * GB)
    }

    #[inline(always)]
    pub const fn gib(size: u64) -> ByteSize {
        ByteSize(size * GIB)
    }

    #[inline(always)]
    pub const fn tb(size: u64) -> ByteSize {
        ByteSize(size * TB)
    }

    #[inline(always)]
    pub const fn tib(size: u64) -> ByteSize {
        ByteSize(size * TIB)
    }

    #[inline(always)]
    pub const fn pb(size: u64) -> ByteSize {
        ByteSize(size * PB)
    }

    #[inline(always)]
    pub const fn pib(size: u64) -> ByteSize {
        ByteSize(size * PIB)
    }

    #[inline(always)]
    pub fn as_u64(&self) -> u64 {
        self.0
    }

    #[inline(always)]
    pub fn to_string_as(&self, si_unit: bool) -> String {
        to_string(self.0, si_unit)
    }
}

pub fn to_string(bytes: u64, si_prefix: bool) -> String {
    let unit = if si_prefix { KIB } else { KB };
    let unit_base = if si_prefix { LN_KIB } else { LN_KB };
    let unit_prefix = if si_prefix {
        UNITS_SI.as_bytes()
    } else {
        UNITS.as_bytes()
    };
    let unit_suffix = if si_prefix { "iB" } else { "B" };

    if bytes < unit {
        format!("{} B", bytes)
    } else {
        let size = bytes as f64;
        let exp = match (size.ln() / unit_base) as usize {
            e if e == 0 => 1,
            e => e,
        };

        format!(
            "{:.1} {}{}",
            (size / unit.pow(exp as u32) as f64),
            unit_prefix[exp - 1] as char,
            unit_suffix
        )
    }
}

impl Display for ByteSize {
    fn fmt(&self, f: &mut Formatter) -> Result {
        f.pad(&to_string(self.0, false))
    }
}

impl Debug for ByteSize {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}", self)
    }
}

macro_rules! commutative_op {
    ($t:ty) => {
        impl Add<$t> for ByteSize {
            type Output = ByteSize;
            #[inline(always)]
            fn add(self, rhs: $t) -> ByteSize {
                ByteSize(self.0 + (rhs as u64))
            }
        }

        impl Add<ByteSize> for $t {
            type Output = ByteSize;
            #[inline(always)]
            fn add(self, rhs: ByteSize) -> ByteSize {
                ByteSize(rhs.0 + (self as u64))
            }
        }

        impl Mul<$t> for ByteSize {
            type Output = ByteSize;
            #[inline(always)]
            fn mul(self, rhs: $t) -> ByteSize {
                ByteSize(self.0 * (rhs as u64))
            }
        }

        impl Mul<ByteSize> for $t {
            type Output = ByteSize;
            #[inline(always)]
            fn mul(self, rhs: ByteSize) -> ByteSize {
                ByteSize(rhs.0 * (self as u64))
            }
        }
    };
}

commutative_op!(u64);
commutative_op!(u32);
commutative_op!(u16);
commutative_op!(u8);

impl Add<ByteSize> for ByteSize {
    type Output = ByteSize;

    #[inline(always)]
    fn add(self, rhs: ByteSize) -> ByteSize {
        ByteSize(self.0 + rhs.0)
    }
}

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

    #[test]
    fn test_arithmetic_op() {
        let x = ByteSize::mb(1);
        let y = ByteSize::kb(100);

        assert_eq!((x + y).as_u64(), 1_100_000u64);

        assert_eq!((x + (100 * 1000) as u64).as_u64(), 1_100_000);

        assert_eq!((x * 2u64).as_u64(), 2_000_000);
    }

    #[test]
    fn test_arithmetic_primitives() {
        let x = ByteSize::mb(1);

        assert_eq!((x + MB as u64).as_u64(), 2_000_000);

        assert_eq!((x + MB as u32).as_u64(), 2_000_000);

        assert_eq!((x + KB as u16).as_u64(), 1_001_000);

        assert_eq!((x + B as u8).as_u64(), 1_000_001);
    }

    #[test]
    fn test_comparison() {
        assert!(ByteSize::mb(1) == ByteSize::kb(1000));
        assert!(ByteSize::mib(1) == ByteSize::kib(1024));
        assert!(ByteSize::mb(1) != ByteSize::kib(1024));
        assert!(ByteSize::mb(1) < ByteSize::kib(1024));
        assert!(ByteSize::b(0) < ByteSize::tib(1));
    }

    fn assert_display(expected: &str, b: ByteSize) {
        assert_eq!(expected, format!("{}", b));
    }

    #[test]
    fn test_display() {
        assert_display("215 B", ByteSize::b(215));
        assert_display("1.0 KB", ByteSize::kb(1));
        assert_display("301.0 KB", ByteSize::kb(301));
        assert_display("419.0 MB", ByteSize::mb(419));
        assert_display("518.0 GB", ByteSize::gb(518));
        assert_display("815.0 TB", ByteSize::tb(815));
        assert_display("609.0 PB", ByteSize::pb(609));
    }

    #[test]
    fn test_display_alignment() {
        assert_eq!("|357 B     |", format!("|{:10}|", ByteSize(357)));
        assert_eq!("|     357 B|", format!("|{:>10}|", ByteSize(357)));
        assert_eq!("|357 B     |", format!("|{:<10}|", ByteSize(357)));
        assert_eq!("|  357 B   |", format!("|{:^10}|", ByteSize(357)));

        assert_eq!("|-----357 B|", format!("|{:->10}|", ByteSize(357)));
        assert_eq!("|357 B-----|", format!("|{:-<10}|", ByteSize(357)));
        assert_eq!("|--357 B---|", format!("|{:-^10}|", ByteSize(357)));
    }

    fn assert_to_string(expected: &str, b: ByteSize, si: bool) {
        assert_eq!(expected.to_string(), b.to_string_as(si));
    }

    #[test]
    fn test_to_string_as() {
        assert_to_string("215 B", ByteSize::b(215), true);
        assert_to_string("215 B", ByteSize::b(215), false);

        assert_to_string("1.0 kiB", ByteSize::kib(1), true);
        assert_to_string("1.0 KB", ByteSize::kib(1), false);

        assert_to_string("293.9 kiB", ByteSize::kb(301), true);
        assert_to_string("301.0 KB", ByteSize::kb(301), false);

        assert_to_string("1.0 MiB", ByteSize::mib(1), true);
        assert_to_string("1048.6 KB", ByteSize::mib(1), false);

        // a bug case: https://github.com/flang-project/bytesize/issues/8
        assert_to_string("1.9 GiB", ByteSize::mib(1907), true);
        assert_to_string("2.0 GB", ByteSize::mib(1908), false);

        assert_to_string("399.6 MiB", ByteSize::mb(419), true);
        assert_to_string("419.0 MB", ByteSize::mb(419), false);

        assert_to_string("482.4 GiB", ByteSize::gb(518), true);
        assert_to_string("518.0 GB", ByteSize::gb(518), false);

        assert_to_string("741.2 TiB", ByteSize::tb(815), true);
        assert_to_string("815.0 TB", ByteSize::tb(815), false);

        assert_to_string("540.9 PiB", ByteSize::pb(609), true);
        assert_to_string("609.0 PB", ByteSize::pb(609), false);
    }

    #[test]
    fn test_default() {
        assert_eq!(ByteSize::b(0), ByteSize::default());
    }

    #[test]
    fn test_to_string() {
        assert_to_string("609.0 PB", ByteSize::pb(609), false);
    }
}
<|endoftext|>


<commit_before>extern crate movecell;
extern crate typed_arena;

use std::cell::Cell;
use std::ops::Deref;
use std::iter::FromIterator;

use movecell::MoveCell;
use typed_arena::Arena;

/// An immovable graph type
pub struct Graph<'a, T: 'a> {
    arena: Arena<Node<'a, T>>,
    root: Cell<Option<&'a Node<'a, T>>>
}

impl <'a, T: 'a> Graph<'a, T> {
    pub fn new() -> Self {
        Graph {
            arena: Arena::new(),
            root: Cell::new(None),
        }
    }

    /// Moves a constructed node into the graph. This allows for construction
    /// of nodes in a more convient fashion.
    #[inline]
    pub fn own_node(&'a self, node: Node<'a, T>) -> &'a Node<'a, T> {
        self.arena.alloc(node)
    }

    /// Get the root node of the graph
    /// # Panics
    /// If root is None
    #[inline]
    pub fn root(&self) -> &Node<'a, T> {
        self.root.get().unwrap()
    }

    /// Set the root node to some `&Node` owned by the graph.
    #[inline]
    pub fn set_root(&'a self, root: &'a Node<'a, T>) -> &'a Node<'a, T> {
        self.root.set(Some(root));
        root
    }
}

/// Most actions applied to the graph are really just applied to the root node
/// recursively (or through an iterator). The graph type is just a facade to
/// own the data for each node.
impl<'a, T> Deref for Graph<'a, T> {
    type Target = Node<'a, T>;

    /// # Panics
    /// If root is not set
    #[inline]
    fn deref(&self) -> &Self::Target {
        self.root()
    }
}

/// Graph node type
pub struct Node<'a, T: 'a> {
    pub datum: T,
    // Allows interior mutability so that the graph can be constructed top down rather than bottom
    // up
    edges: MoveCell<Option<Vec<&'a Node<'a, T>>>>
}

impl<'a, T: 'a> Node<'a, T> {
    pub fn new(datum: T) -> Node<'a, T> {
        Node {
            datum: datum,
            edges: MoveCell::new(None),
        }
    }

    /// Adds a `&Node<T>` to the list of edges
    pub fn add_edge(&self, edge: &'a Node<'a, T>) -> &'a Node<'a, T> {
        let mut edges = self.edges.take().unwrap_or(Vec::new());
        edges.push(edge);
        self.edges.replace(Some(edges));
        edge
    }

    /// Iterator adapter for Depth-first traversals of the graph
    pub fn dfs(&'a self) -> DfsIter<T> {
        DfsIter {
            branch_points: vec![(None, self)]
        }
    }
}

impl<'a, T> FromIterator<&'a Node<'a, T>> for &'a Node<'a, T> {
    /// Makes the assumption that the first node to come off an IntoIterator of `&Node` is the root
    /// node. This happens to be correct for BFS and DFS iteration. Any users of `.map()` must be
    /// careful to ensure that the root node is the first produced node.
    ///
    /// NOTE: When running the evaluations this will stop at the first `None` seen. If the
    /// iteration performs operations on any nodes after a single iteration returns a `None`,
    /// those subsequent executions will be skipped.
    ///
    /// # Panics
    /// If the iteration doesn't produce any `&Node`s
    fn from_iter<I: IntoIterator<Item=&'a Node<'a, T>>>(iterable: I) -> Self {
        let mut iter = iterable.into_iter();
        let root = iter.next().unwrap();
        while iter.next().is_some() {  };
        root
    }
}

/// Depth-first iterator adapter for Nodes
pub struct DfsIter<'a, T: 'a> {
    branch_points: Vec<(Option<usize>, &'a Node<'a, T>)>,
}

impl<'a, T> Iterator for DfsIter<'a, T> {
    type Item = &'a Node<'a, T>;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(branch_point) = self.branch_points.pop() {
            let (index, node) = branch_point;

            if let Some(edges) = node.edges.take() {
                let found_node = match index {
                    None => {
                        self.branch_points.push((Some(0), node));
                        Some(node)
                    },
                    Some(index) => {
                        if index < edges.len() {
                            self.branch_points.push((Some(index + 1), node));
                            self.branch_points.push((None, edges[index]));
                        }
                        None
                    }
                };

                node.edges.replace(Some(edges));
                if found_node.is_some() {
                    return found_node;
                }
            } else {
                return Some(node);
            }
        }
        None
    }
}

#[test]
fn it_works() {
    let graph = Graph::new();
    let node1 = graph.set_root(graph.own_node(Node::new(1)));
    let node2 = node1.add_edge(graph.own_node(Node::new(2)));
    let _node3 = node1.add_edge(graph.own_node(Node::new(3)));
    let _node4 = node2.add_edge(graph.own_node(Node::new(4)));
    let _node5 = node2.add_edge(graph.own_node(Node::new(5)));

    println!("Graph 1 (original):");
    for node in graph.dfs() {
        println!("{}", node.datum);
    }

    println!("Graph 1 (mapped):");
    let graph2 = Graph::new();
    let root = graph.dfs().map(|e| graph2.own_node(Node::new(e.datum as f32 * 2.1))).collect();
    graph2.set_root(root);
    for node in graph2.dfs() {
        println!("{}", node.datum);
    }
}
<commit_msg>Update documentation to get better help on the reddit thread<commit_after>extern crate movecell;
extern crate typed_arena;

use std::cell::Cell;
use std::ops::Deref;
use std::iter::FromIterator;

use movecell::MoveCell;
use typed_arena::Arena;

/// An immovable graph type
pub struct Graph<'a, T: 'a> {
    arena: Arena<Node<'a, T>>,
    root: Cell<Option<&'a Node<'a, T>>>
}

impl <'a, T: 'a> Graph<'a, T> {
    pub fn new() -> Self {
        Graph {
            arena: Arena::new(),
            root: Cell::new(None),
        }
    }

    /// Moves a constructed node into the graph. This allows for construction
    /// of nodes in a more convient fashion.
    #[inline]
    pub fn own_node(&'a self, node: Node<'a, T>) -> &'a Node<'a, T> {
        self.arena.alloc(node)
    }

    /// Get the root node of the graph
    /// # Panics
    /// If root is None
    #[inline]
    pub fn root(&self) -> &Node<'a, T> {
        self.root.get().unwrap()
    }

    /// Set the root node to some `&Node` owned by the graph.
    #[inline]
    pub fn set_root(&'a self, root: &'a Node<'a, T>) -> &'a Node<'a, T> {
        self.root.set(Some(root));
        root
    }
}

/// Most actions applied to the graph are really just applied to the root node
/// recursively (or through an iterator). The graph type is just a facade to
/// own the data for each node.
impl<'a, T> Deref for Graph<'a, T> {
    type Target = Node<'a, T>;

    /// # Panics
    /// If root is not set
    #[inline]
    fn deref(&self) -> &Self::Target {
        self.root()
    }
}

/// Graph node type
pub struct Node<'a, T: 'a> {
    pub datum: T,
    // Allows interior mutability so that the graph can be constructed top down rather than bottom
    // up
    edges: MoveCell<Option<Vec<&'a Node<'a, T>>>>
}

impl<'a, T: 'a> Node<'a, T> {
    pub fn new(datum: T) -> Node<'a, T> {
        Node {
            datum: datum,
            edges: MoveCell::new(None),
        }
    }

    /// Adds a `&Node<T>` to the list of edges
    pub fn add_edge(&self, edge: &'a Node<'a, T>) -> &'a Node<'a, T> {
        let mut edges = self.edges.take().unwrap_or(Vec::new());
        edges.push(edge);
        self.edges.replace(Some(edges));
        edge
    }

    /// Iterator adapter for Depth-first traversals of the graph
    pub fn dfs(&'a self) -> DfsIter<T> {
        DfsIter {
            branch_points: vec![(None, self)]
        }
    }
}

impl<'a, T> FromIterator<&'a Node<'a, T>> for &'a Node<'a, T> {
    /// Makes the assumption that the first node to come off an IntoIterator of `&Node` is the root
    /// node. This happens to be correct for BFS and DFS iteration. Any users of `.map()` must be
    /// careful to ensure that the root node is the first produced node.
    ///
    /// NOTE: When running the evaluations this will stop at the first `None` seen. If the
    /// iteration performs operations on any nodes after a single iteration returns a `None`,
    /// those subsequent executions will be skipped.
    ///
    /// # Panics
    /// If the iteration doesn't produce any `&Node`s
    fn from_iter<I: IntoIterator<Item=&'a Node<'a, T>>>(iterable: I) -> Self {
        let mut iter = iterable.into_iter();
        let root = iter.next().unwrap();
        while iter.next().is_some() {  };
        root
    }
}

/// Depth-first iterator adapter for Nodes
pub struct DfsIter<'a, T: 'a> {
    branch_points: Vec<(Option<usize>, &'a Node<'a, T>)>,
}

impl<'a, T> Iterator for DfsIter<'a, T> {
    type Item = &'a Node<'a, T>;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(branch_point) = self.branch_points.pop() {
            let (index, node) = branch_point;

            if let Some(edges) = node.edges.take() {
                let found_node = match index {
                    None => {
                        self.branch_points.push((Some(0), node));
                        Some(node)
                    },
                    Some(index) => {
                        if index < edges.len() {
                            self.branch_points.push((Some(index + 1), node));
                            self.branch_points.push((None, edges[index]));
                        }
                        None
                    }
                };

                node.edges.replace(Some(edges));
                if found_node.is_some() {
                    return found_node;
                }
            } else {
                return Some(node);
            }
        }
        None
    }
}

#[test]
fn it_works() {
    let graph = Graph::new();
    let node1 = graph.set_root(graph.own_node(Node::new(1)));
    let node2 = node1.add_edge(graph.own_node(Node::new(2)));
    let _node3 = node1.add_edge(graph.own_node(Node::new(3)));
    let _node4 = node2.add_edge(graph.own_node(Node::new(4)));
    let _node5 = node2.add_edge(graph.own_node(Node::new(5)));

    println!("Graph 1 (original):");
    for node in graph.dfs() {
        println!("{}", node.datum);
    }

    println!("Graph 1 (mapped):");
    let graph2 = Graph::new();
    // How do I make sure that they children are updated? Seems like the job of collect maybe
    let root = graph.dfs().map(|e| graph2.own_node(Node::new(e.datum as f32 * 2.1))).collect();
    graph2.set_root(root);
    for node in graph2.dfs() {
        println!("{}", node.datum);
    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate regex;

use std::collections::HashMap;

use hyper::server::{Handler, Request, Response};
use regex::RegexSet;

type RouterFn = fn(Request, Response);

const MIN_ROUTES: usize = 2;

pub struct Router {
    not_found: Option<RouterFn>,
    routes: RegexSet,
    route_list: Vec<String>,
    route_map: HashMap<String, RouterFn>
}

impl Handler for Router {
    // The handle method for the router simply tries to match the URI against
    // the first pattern that it can which in turn calls its associated handle
    // function passing the hyper Request and Response structures.
    fn handle(&self, req: Request, res: Response) {
        let uri = format!("{}", req.uri);
        let matches = self.routes.matches(&uri);
        let route = matches.iter().next();
        match route {
            Some(r) => {
                let key = &self.route_list[r];
                let handler = self.route_map.get(key).unwrap();
                handler(req, res);
            },
            None => self.not_found.unwrap()(req, res)
        }
    }
}

impl Router {
    /// Construct a new Router to maintain the routes and their handler
    /// functions.
    pub fn new() -> Router {
        Router {
            not_found: None,
            routes: RegexSet::new(&["", ""]).unwrap(),
            route_list: Vec::new(),
            route_map: HashMap::new(),
        }
    }

    /// Add a route to the router and give it a function to call when the route
    /// is matched against.
    pub fn add_route(&mut self, route: &str, handler: RouterFn) {
        self.route_list.push(route.to_owned());
        self.route_map.insert(route.to_owned(), handler);
    }

    /// This function ensures that a valid RegexSet could be made from the route
    /// vector that was built while using the `add_route` function. It also
    /// requires that there exist two or more routes so that the RegexSet can be
    /// successfully constructed.
    ///
    /// It will also ensure that there is a handler for routes that do not match
    /// any available in the set.
    pub fn finalize(&mut self) -> Result<(), String> {
        if self.route_list.len() < MIN_ROUTES {
            return Err("The router must contain 2 or more routes".to_owned());
        }

        // Check if the user added a 404 handler, else use the default.
        match self.not_found {
            Some(_) => {},
            None => { self.not_found = Some(default_not_found); }
        }

        let re_routes = RegexSet::new(self.route_list.iter());
        match re_routes {
            Ok(r) => {
                self.routes = r;
                Ok(())
            }
            Err(e) => {
                Err(format!("Error making RegexSet: {}", e))
            }
        }
    }

    /// Add a function to handle routes that get no matches.
    pub fn add_not_found(&mut self, not_found: RouterFn) {
        self.not_found = Some(not_found)
    }
}

fn default_not_found(req: Request, res: Response) {
    let message = format!("No route handler found for {}", req.uri);
    res.send(message.as_bytes()).unwrap();
}

fn test_handler(_: Request, _: Response) {}

#[test]
#[should_panic]
fn less_than_two_routes() {
    let mut router = Router::new();
    router.add_route("/", test_handler);
    router.finalize().unwrap();
}
<commit_msg>make sure type is public<commit_after>extern crate hyper;
extern crate regex;

use std::collections::HashMap;

use hyper::server::{Handler, Request, Response};
use regex::RegexSet;

pub type RouterFn = fn(Request, Response);

const MIN_ROUTES: usize = 2;

pub struct Router {
    not_found: Option<RouterFn>,
    routes: RegexSet,
    route_list: Vec<String>,
    route_map: HashMap<String, RouterFn>
}

impl Handler for Router {
    // The handle method for the router simply tries to match the URI against
    // the first pattern that it can which in turn calls its associated handle
    // function passing the hyper Request and Response structures.
    fn handle(&self, req: Request, res: Response) {
        let uri = format!("{}", req.uri);
        let matches = self.routes.matches(&uri);
        let route = matches.iter().next();
        match route {
            Some(r) => {
                let key = &self.route_list[r];
                let handler = self.route_map.get(key).unwrap();
                handler(req, res);
            },
            None => self.not_found.unwrap()(req, res)
        }
    }
}

impl Router {
    /// Construct a new Router to maintain the routes and their handler
    /// functions.
    pub fn new() -> Router {
        Router {
            not_found: None,
            routes: RegexSet::new(&["", ""]).unwrap(),
            route_list: Vec::new(),
            route_map: HashMap::new(),
        }
    }

    /// Add a route to the router and give it a function to call when the route
    /// is matched against.
    pub fn add_route(&mut self, route: &str, handler: RouterFn) {
        self.route_list.push(route.to_owned());
        self.route_map.insert(route.to_owned(), handler);
    }

    /// This function ensures that a valid RegexSet could be made from the route
    /// vector that was built while using the `add_route` function. It also
    /// requires that there exist two or more routes so that the RegexSet can be
    /// successfully constructed.
    ///
    /// It will also ensure that there is a handler for routes that do not match
    /// any available in the set.
    pub fn finalize(&mut self) -> Result<(), String> {
        if self.route_list.len() < MIN_ROUTES {
            return Err("The router must contain 2 or more routes".to_owned());
        }

        // Check if the user added a 404 handler, else use the default.
        match self.not_found {
            Some(_) => {},
            None => { self.not_found = Some(default_not_found); }
        }

        let re_routes = RegexSet::new(self.route_list.iter());
        match re_routes {
            Ok(r) => {
                self.routes = r;
                Ok(())
            }
            Err(e) => {
                Err(format!("Error making RegexSet: {}", e))
            }
        }
    }

    /// Add a function to handle routes that get no matches.
    pub fn add_not_found(&mut self, not_found: RouterFn) {
        self.not_found = Some(not_found)
    }
}

fn default_not_found(req: Request, res: Response) {
    let message = format!("No route handler found for {}", req.uri);
    res.send(message.as_bytes()).unwrap();
}

fn test_handler(_: Request, _: Response) {}

#[test]
#[should_panic]
fn less_than_two_routes() {
    let mut router = Router::new();
    router.add_route("/", test_handler);
    router.finalize().unwrap();
}
<|endoftext|>


<commit_before>extern crate byteorder;
extern crate postgres;

use byteorder::{BigEndian, WriteBytesExt};
use postgres::ReadWithInfo;
use postgres::error::Error;
use postgres::types::{Type, ToSql, SessionInfo, IsNull};
use std::error;
use std::io::prelude::*;
use std::io::{self, Cursor};

pub trait StreamingIterator {
    type Item: ?Sized;

    fn next(&mut self) -> Option<&Self::Item>;
}

impl<'a, T: 'a+?Sized, I: Iterator<Item = &'a T>> StreamingIterator for I {
    type Item = T;

    fn next(&mut self) -> Option<&T> {
        unsafe { std::mem::transmute(Iterator::next(self)) }
    }
}

#[derive(Copy, Clone)]
enum ReadState {
    Header,
    Body(usize),
    Footer,
}

pub struct BinaryCopyReader<'a, I> {
    types: &'a [Type],
    state: ReadState,
    it: I,
    buf: Cursor<Vec<u8>>,
}

impl<'a, I> BinaryCopyReader<'a, I> where I: StreamingIterator<Item = ToSql> {
    pub fn new(types: &'a [Type], it: I) -> BinaryCopyReader<'a, I> {
        let mut buf = vec![];
        let _ = buf.write(b"PGCOPY\n\xff\r\n\0");
        let _ = buf.write_i32::<BigEndian>(0);
        let _ = buf.write_i32::<BigEndian>(0);

        BinaryCopyReader {
            types: types,
            state: ReadState::Header,
            it: it,
            buf: Cursor::new(buf),
        }
    }

    fn transition(&mut self, info: &SessionInfo) -> io::Result<()> {
        enum Op<'a> {
            Value(usize, &'a ToSql),
            Footer,
            Nothing,
        }

        self.buf.set_position(0);
        self.buf.get_mut().clear();

        let op = match (self.state, self.it.next()) {
            (ReadState::Header, Some(value)) => {
                self.state = ReadState::Body(0);
                Op::Value(0, value)
            }
            (ReadState::Body(old_idx), Some(value)) => {
                let idx = (old_idx + 1) % self.types.len();
                self.state = ReadState::Body(idx);
                Op::Value(idx, value)
            }
            (ReadState::Header, None) | (ReadState::Body(_), None) => {
                self.state = ReadState::Footer;
                Op::Footer
            }
            (ReadState::Footer, _) => Op::Nothing,
        };

        match op {
            Op::Value(idx, value) => {
                if idx == 0 {
                    let len = self.types.len();
                    let len = if len > i16::max_value() as usize {
                        let err: Box<error::Error+Sync+Send> = "value too large to transmit".into();
                        return Err(io::Error::new(io::ErrorKind::InvalidInput, Error::Conversion(err)));
                    } else {
                        len as i16
                    };
                    let _ = self.buf.write_i16::<BigEndian>(len);
                }

                let len_pos = self.buf.position();
                let _ = self.buf.write_i32::<BigEndian>(0); // space for length
                let len = match value.to_sql_checked(&self.types[idx], &mut self.buf, info) {
                    Ok(IsNull::Yes) => -1,
                    Ok(IsNull::No) => {
                        let len = self.buf.position() - 4 - len_pos;
                        if len > i32::max_value() as u64 {
                            let err: Box<error::Error+Sync+Send> = "value too large to transmit".into();
                            return Err(io::Error::new(io::ErrorKind::InvalidInput, Error::Conversion(err)));
                        } else {
                            len as i32
                        }
                    }
                    Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidInput, e)),
                };
                self.buf.set_position(len_pos);
                let _ = self.buf.write_i32::<BigEndian>(len);
            }
            Op::Footer => {
                let _ = self.buf.write_i16::<BigEndian>(-1);
            }
            Op::Nothing => {}
        }

        self.buf.set_position(0);
        Ok(())
    }
}

impl<'a, I> ReadWithInfo for BinaryCopyReader<'a, I> where I: StreamingIterator<Item = ToSql> {
    fn read_with_info(&mut self, buf: &mut [u8], info: &SessionInfo) -> io::Result<usize> {
        if self.buf.position() == self.buf.get_ref().len() as u64 {
            try!(self.transition(info));
        }
        self.buf.read(buf)
    }
}

#[cfg(test)]
mod test {
    use super::BinaryCopyReader;
    use postgres::{Connection, SslMode};
    use postgres::types::{Type, ToSql};

    #[test]
    fn basic() {
        let conn = Connection::connect("postgres://postgres@localhost", &SslMode::None).unwrap();
        conn.execute("CREATE TEMPORARY TABLE foo (id INT PRIMARY KEY, bar VARCHAR)", &[]).unwrap();

        let stmt = conn.prepare("COPY foo (id, bar) FROM STDIN BINARY").unwrap();

        let types = &[Type::Int4, Type::Varchar];
        let values: Vec<Box<ToSql>> = vec![Box::new(1i32), Box::new("foobar"),
                                           Box::new(2i32), Box::new("bizbuz")];
        let values = values.iter().map(|e| &**e);
        let mut reader = BinaryCopyReader::new(types, values);

        stmt.copy_in(&[], &mut reader).unwrap();

        let stmt = conn.prepare("SELECT id, bar FROM foo ORDER BY id").unwrap();
        assert_eq!(vec![(1i32, "foobar".to_string()), (2i32, "bizbuz".to_string())],
                   stmt.query(&[])
                        .unwrap()
                        .into_iter()
                        .map(|r| (r.get(0), r.get(1)))
                        .collect::<Vec<(i32, String)>>());
    }

    #[test]
    fn big() {
        let conn = Connection::connect("postgres://postgres@localhost", &SslMode::None).unwrap();
        conn.execute("CREATE TEMPORARY TABLE foo (id INT PRIMARY KEY, bar VARCHAR)", &[]).unwrap();

        let stmt = conn.prepare("COPY foo (id, bar) FROM STDIN BINARY").unwrap();

        let types = &[Type::Int4, Type::Varchar];
        let mut values: Vec<Box<ToSql>> = vec![];
        for i in 0..10000i32 {
            values.push(Box::new(i));
            values.push(Box::new(format!("the value for {}", i)));
        }

        let values = values.iter().map(|e| &**e);
        let mut reader = BinaryCopyReader::new(types, values);

        stmt.copy_in(&[], &mut reader).unwrap();

        let stmt = conn.prepare("SELECT id, bar FROM foo ORDER BY id").unwrap();
        let result = stmt.query(&[]).unwrap();
        assert_eq!(10000, result.len());
        for (i, row) in result.into_iter().enumerate() {
            assert_eq!(i as i32, row.get(0));
            assert_eq!(format!("the value for {}", i), row.get::<_, String>(1));
        }
    }
}
<commit_msg>Fix import location<commit_after>extern crate byteorder;
extern crate postgres;

use byteorder::{BigEndian, WriteBytesExt};
use postgres::error::Error;
use postgres::types::{Type, ToSql, SessionInfo, IsNull, ReadWithInfo};
use std::error;
use std::io::prelude::*;
use std::io::{self, Cursor};

pub trait StreamingIterator {
    type Item: ?Sized;

    fn next(&mut self) -> Option<&Self::Item>;
}

impl<'a, T: 'a+?Sized, I: Iterator<Item = &'a T>> StreamingIterator for I {
    type Item = T;

    fn next(&mut self) -> Option<&T> {
        unsafe { std::mem::transmute(Iterator::next(self)) }
    }
}

#[derive(Copy, Clone)]
enum ReadState {
    Header,
    Body(usize),
    Footer,
}

pub struct BinaryCopyReader<'a, I> {
    types: &'a [Type],
    state: ReadState,
    it: I,
    buf: Cursor<Vec<u8>>,
}

impl<'a, I> BinaryCopyReader<'a, I> where I: StreamingIterator<Item = ToSql> {
    pub fn new(types: &'a [Type], it: I) -> BinaryCopyReader<'a, I> {
        let mut buf = vec![];
        let _ = buf.write(b"PGCOPY\n\xff\r\n\0");
        let _ = buf.write_i32::<BigEndian>(0);
        let _ = buf.write_i32::<BigEndian>(0);

        BinaryCopyReader {
            types: types,
            state: ReadState::Header,
            it: it,
            buf: Cursor::new(buf),
        }
    }

    fn transition(&mut self, info: &SessionInfo) -> io::Result<()> {
        enum Op<'a> {
            Value(usize, &'a ToSql),
            Footer,
            Nothing,
        }

        self.buf.set_position(0);
        self.buf.get_mut().clear();

        let op = match (self.state, self.it.next()) {
            (ReadState::Header, Some(value)) => {
                self.state = ReadState::Body(0);
                Op::Value(0, value)
            }
            (ReadState::Body(old_idx), Some(value)) => {
                let idx = (old_idx + 1) % self.types.len();
                self.state = ReadState::Body(idx);
                Op::Value(idx, value)
            }
            (ReadState::Header, None) | (ReadState::Body(_), None) => {
                self.state = ReadState::Footer;
                Op::Footer
            }
            (ReadState::Footer, _) => Op::Nothing,
        };

        match op {
            Op::Value(idx, value) => {
                if idx == 0 {
                    let len = self.types.len();
                    let len = if len > i16::max_value() as usize {
                        let err: Box<error::Error+Sync+Send> = "value too large to transmit".into();
                        return Err(io::Error::new(io::ErrorKind::InvalidInput, Error::Conversion(err)));
                    } else {
                        len as i16
                    };
                    let _ = self.buf.write_i16::<BigEndian>(len);
                }

                let len_pos = self.buf.position();
                let _ = self.buf.write_i32::<BigEndian>(0); // space for length
                let len = match value.to_sql_checked(&self.types[idx], &mut self.buf, info) {
                    Ok(IsNull::Yes) => -1,
                    Ok(IsNull::No) => {
                        let len = self.buf.position() - 4 - len_pos;
                        if len > i32::max_value() as u64 {
                            let err: Box<error::Error+Sync+Send> = "value too large to transmit".into();
                            return Err(io::Error::new(io::ErrorKind::InvalidInput, Error::Conversion(err)));
                        } else {
                            len as i32
                        }
                    }
                    Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidInput, e)),
                };
                self.buf.set_position(len_pos);
                let _ = self.buf.write_i32::<BigEndian>(len);
            }
            Op::Footer => {
                let _ = self.buf.write_i16::<BigEndian>(-1);
            }
            Op::Nothing => {}
        }

        self.buf.set_position(0);
        Ok(())
    }
}

impl<'a, I> ReadWithInfo for BinaryCopyReader<'a, I> where I: StreamingIterator<Item = ToSql> {
    fn read_with_info(&mut self, buf: &mut [u8], info: &SessionInfo) -> io::Result<usize> {
        if self.buf.position() == self.buf.get_ref().len() as u64 {
            try!(self.transition(info));
        }
        self.buf.read(buf)
    }
}

#[cfg(test)]
mod test {
    use super::BinaryCopyReader;
    use postgres::{Connection, SslMode};
    use postgres::types::{Type, ToSql};

    #[test]
    fn basic() {
        let conn = Connection::connect("postgres://postgres@localhost", &SslMode::None).unwrap();
        conn.execute("CREATE TEMPORARY TABLE foo (id INT PRIMARY KEY, bar VARCHAR)", &[]).unwrap();

        let stmt = conn.prepare("COPY foo (id, bar) FROM STDIN BINARY").unwrap();

        let types = &[Type::Int4, Type::Varchar];
        let values: Vec<Box<ToSql>> = vec![Box::new(1i32), Box::new("foobar"),
                                           Box::new(2i32), Box::new("bizbuz")];
        let values = values.iter().map(|e| &**e);
        let mut reader = BinaryCopyReader::new(types, values);

        stmt.copy_in(&[], &mut reader).unwrap();

        let stmt = conn.prepare("SELECT id, bar FROM foo ORDER BY id").unwrap();
        assert_eq!(vec![(1i32, "foobar".to_string()), (2i32, "bizbuz".to_string())],
                   stmt.query(&[])
                        .unwrap()
                        .into_iter()
                        .map(|r| (r.get(0), r.get(1)))
                        .collect::<Vec<(i32, String)>>());
    }

    #[test]
    fn big() {
        let conn = Connection::connect("postgres://postgres@localhost", &SslMode::None).unwrap();
        conn.execute("CREATE TEMPORARY TABLE foo (id INT PRIMARY KEY, bar VARCHAR)", &[]).unwrap();

        let stmt = conn.prepare("COPY foo (id, bar) FROM STDIN BINARY").unwrap();

        let types = &[Type::Int4, Type::Varchar];
        let mut values: Vec<Box<ToSql>> = vec![];
        for i in 0..10000i32 {
            values.push(Box::new(i));
            values.push(Box::new(format!("the value for {}", i)));
        }

        let values = values.iter().map(|e| &**e);
        let mut reader = BinaryCopyReader::new(types, values);

        stmt.copy_in(&[], &mut reader).unwrap();

        let stmt = conn.prepare("SELECT id, bar FROM foo ORDER BY id").unwrap();
        let result = stmt.query(&[]).unwrap();
        assert_eq!(10000, result.len());
        for (i, row) in result.into_iter().enumerate() {
            assert_eq!(i as i32, row.get(0));
            assert_eq!(format!("the value for {}", i), row.get::<_, String>(1));
        }
    }
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;

use serde_json::Error;

#[derive(Debug, Serialize, Deserialize)]
pub struct Site {
    id: u64,
    kind: String,
    position: (f64, f64, f64),
    tags: Option<Vec<String>>,
}

impl std::str::FromStr for Site {
    type Err = Error;
    fn from_str(source: &str) -> Result<Site, Self::Err> {
        serde_json::from_str(source)
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Vertex {
    source: u64,
    target: u64,
    delta: (i32, i32, i32),
    tags: Option<Vec<String>>,
}

impl std::str::FromStr for Vertex {
    type Err = Error;
    fn from_str(source: &str) -> Result<Vertex, Self::Err> {
        serde_json::from_str(source)
    }
}

#[cfg(test)]
mod tests {
    use super::{Site, Vertex};
    use std::str::FromStr;

    #[test]
    fn vertex_site_can_be_read_from_str() {
        let data = r#"
            {"id": 0, "kind": "Fe", "position": [0, 0, 0]}
        "#;
        let site_result = Site::from_str(data);
        assert!(site_result.is_ok());
    }

    #[test]
    fn site_will_take_optional_tags() {
        let data = r#"
            {"id": 0, "kind": "Fe", "position": [0, 0, 0], "tags": ["core", "inner"]}
        "#;
        let site_result: Result<Site, _> = data.parse();
        assert!(site_result.is_ok());
        assert_eq!(site_result.unwrap().tags, Some(vec!["core".to_string(), "inner".to_string()]));
    }

    #[test]
    fn site_will_parse_id() {
        let data = r#"
            {"id": 0, "kind": "Fe", "position": [0, 0, 0]}
        "#;
        let site_result: Result<Site, _> = data.parse();
        assert!(site_result.is_ok());
        assert_eq!(site_result.unwrap().id, 0);
    }

    #[test]
    fn vertex_will_take_optional_tags() {
        let data = r#"
            {"source": 0, "target": 0, "delta": [0, 0, 1], "tags": ["core", "inner"]}
        "#;
        let site_result: Result<Vertex, _> = data.parse();
        assert!(site_result.is_ok());
        assert_eq!(site_result.unwrap().tags, Some(vec!["core".to_string(), "inner".to_string()]));
    }
}
<commit_msg>Write basic lattice and consistency checks<commit_after>extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;

use serde_json::Error;
use std::collections::HashSet;

#[derive(Debug, Serialize, Deserialize)]
pub struct Site {
    id: u64,
    kind: String,
    position: (f64, f64, f64),
    tags: Option<Vec<String>>,
}

impl std::str::FromStr for Site {
    type Err = Error;
    fn from_str(source: &str) -> Result<Site, Self::Err> {
        serde_json::from_str(source)
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Vertex {
    source: u64,
    target: u64,
    delta: (i32, i32, i32),
    tags: Option<Vec<String>>,
}

impl std::str::FromStr for Vertex {
    type Err = Error;
    fn from_str(source: &str) -> Result<Vertex, Self::Err> {
        serde_json::from_str(source)
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Lattice {
    sites: Vec<Site>,
    vertices: Vec<Vertex>,
}

#[derive(Debug)]
pub enum LatticeError {
    JsonParseError(Error),
    InconsistentVertices,
    NonUniqueSiteIds,
}

impl Lattice {
    fn are_vertices_consistent(&self) -> bool {
        let site_ids: HashSet<_> = self.sites.iter().map(|site| site.id).collect();
        let vertex_ids: HashSet<_> = self.vertices.iter().map(|vertex| vertex.source).chain(
            self.vertices.iter().map(|vertex| vertex.target)
        ).collect();
        vertex_ids.is_subset(&site_ids)
    }

    fn are_site_ids_unique(&self) -> bool {
        let site_ids: Vec<_> = self.sites.iter().map(|site| site.id).collect();
        let unique_site_ids: HashSet<_> = site_ids.iter().collect();
        site_ids.len() == unique_site_ids.len()
    }

    pub fn validate(self) -> Result<Self, LatticeError> {
        if !self.are_site_ids_unique() {
            return Err(LatticeError::NonUniqueSiteIds)
        }
        if !self.are_vertices_consistent() {
            return Err(LatticeError::InconsistentVertices)
        }
        Ok(self)
    }
}

impl std::str::FromStr for Lattice {
    type Err = LatticeError;
    fn from_str(source: &str) -> Result<Lattice, Self::Err> {
        serde_json::from_str(source)
            .map_err(|err| LatticeError::JsonParseError(err))
            .and_then(|lattice: Lattice| lattice.validate())
    }
}

#[cfg(test)]
mod tests {
    use super::{Site, Vertex, Lattice};
    use std::str::FromStr;

    #[test]
    fn vertex_site_can_be_read_from_str() {
        let data = r#"
            {"id": 0, "kind": "Fe", "position": [0, 0, 0]}
        "#;
        let site_result = Site::from_str(data);
        assert!(site_result.is_ok());
    }

    #[test]
    fn site_will_take_optional_tags() {
        let data = r#"
            {"id": 0, "kind": "Fe", "position": [0, 0, 0], "tags": ["core", "inner"]}
        "#;
        let site_result: Result<Site, _> = data.parse();
        assert!(site_result.is_ok());
        assert_eq!(site_result.unwrap().tags, Some(vec!["core".to_string(), "inner".to_string()]));
    }

    #[test]
    fn site_will_parse_id() {
        let data = r#"
            {"id": 0, "kind": "Fe", "position": [0, 0, 0]}
        "#;
        let site_result: Result<Site, _> = data.parse();
        assert!(site_result.is_ok());
        assert_eq!(site_result.unwrap().id, 0);
    }

    #[test]
    fn vertex_will_take_optional_tags() {
        let data = r#"
            {"source": 0, "target": 0, "delta": [0, 0, 1], "tags": ["core", "inner"]}
        "#;
        let site_result: Result<Vertex, _> = data.parse();
        assert!(site_result.is_ok());
        assert_eq!(site_result.unwrap().tags, Some(vec!["core".to_string(), "inner".to_string()]));
    }

    #[test]
    fn lattice_example() {
        let data = r#"
            {
                "sites": [
                    {"id": 0, "kind": "Fe", "position": [0, 0, 0]}
                ],
                "vertices": [
                    {"source": 0, "target": 0, "delta": [0, 0, 1], "tags": ["core", "inner"]}
                ]
            }
        "#;
        let site_result: Result<Lattice, _> = data.parse();
        assert!(site_result.is_ok());
    }

    #[test]
    fn lattice_will_fail_for_inconsistent_vertices() {
        let data = r#"
            {
                "sites": [
                    {"id": 0, "kind": "Fe", "position": [0, 0, 0]}
                ],
                "vertices": [
                    {"source": 0, "target": 1, "delta": [0, 0, 1], "tags": ["core", "inner"]}
                ]
            }
        "#;
        let site_result: Result<Lattice, _> = data.parse();
        assert!(site_result.is_err());
    }

    #[test]
    fn lattice_will_fail_for_duplicated_site_ids() {
        let data = r#"
            {
                "sites": [
                    {"id": 0, "kind": "Fe", "position": [0, 0, 0]},
                    {"id": 0, "kind": "Fe+", "position": [0, 0, 0]}
                ],
                "vertices": [
                    {"source": 0, "target": 0, "delta": [0, 0, 1], "tags": ["core", "inner"]}
                ]
            }
        "#;
        let site_result: Result<Lattice, _> = data.parse();
        println!("{:?}", site_result);
        assert!(site_result.is_err());
    }
}
<|endoftext|>


<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_async = "<desired version>"
//! ```
//!
//! ### Example
//!
//! ```rust
//! # use mysql_async::{Result, test_misc::get_opts};
//! use mysql_async::prelude::*;
//! # use std::env;
//!
//! #[derive(Debug, PartialEq, Eq, Clone)]
//! struct Payment {
//!     customer_id: i32,
//!     amount: i32,
//!     account_name: Option<String>,
//! }
//!
//! #[tokio::main]
//! async fn main() -> Result<()> {
//!     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 = /* ... */
//!     # get_opts();
//!
//!     let pool = mysql_async::Pool::new(database_url);
//!     let mut conn = pool.get_conn().await?;
//!
//!     // Create temporary table
//!     conn.query_drop(
//!         r"CREATE TEMPORARY TABLE payment (
//!             customer_id int not null,
//!             amount int not null,
//!             account_name text
//!         )"
//!     ).await?;
//!
//!     // Save payments
//!     let params = payments.clone().into_iter().map(|payment| {
//!         params! {
//!             "customer_id" => payment.customer_id,
//!             "amount" => payment.amount,
//!             "account_name" => payment.account_name,
//!         }
//!     });
//!
//!     conn.exec_batch(
//!         r"INSERT INTO payment (customer_id, amount, account_name)
//!           VALUES (:customer_id, :amount, :account_name)",
//!         params,
//!     ).await?;
//!
//!     // Load payments from database. Type inference will work here.
//!     let loaded_payments = conn.exec_map(
//!         "SELECT customer_id, amount, account_name FROM payment",
//!         (),
//!         |(customer_id, amount, account_name)| Payment { customer_id, amount, account_name },
//!     ).await?;
//!
//!     // Dropped connection will go to the pool
//!     drop(conn);
//!
//!     // Pool must be disconnected explicitly because
//!     // it's an asynchronous operation.
//!     pool.disconnect().await?;
//!
//!     assert_eq!(loaded_payments, payments);
//!
//!     // the async fn returns Result, so
//!     Ok(())
//! }
//! ```

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

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

pub use mysql_common::{chrono, constants as consts, params, time, uuid};

use std::sync::Arc;

mod buffer_pool;

#[macro_use]
mod macros;
mod conn;
mod connection_like;
/// Errors used in this crate
mod error;
mod io;
mod local_infile_handler;
mod opts;
mod query;
mod queryable;

type BoxFuture<'a, T> = futures_core::future::BoxFuture<'a, Result<T>>;

static BUFFER_POOL: once_cell::sync::Lazy<Arc<crate::buffer_pool::BufferPool>> =
    once_cell::sync::Lazy::new(|| Default::default());

#[doc(inline)]
pub use self::conn::{binlog_stream::BinlogStream, Conn};

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

#[doc(inline)]
pub use self::error::{DriverError, Error, IoError, ParseError, Result, ServerError, UrlError};

#[doc(inline)]
pub use self::query::QueryWithParams;

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

#[doc(inline)]
pub use self::opts::{
    Opts, OptsBuilder, PoolConstraints, PoolOpts, SslOpts, DEFAULT_INACTIVE_CONNECTION_TTL,
    DEFAULT_POOL_CONSTRAINTS, DEFAULT_STMT_CACHE_SIZE, DEFAULT_TTL_CHECK_INTERVAL,
};

#[doc(inline)]
pub use self::local_infile_handler::{builtin::WhiteListFsLocalInfileHandler, InfileHandlerFuture};

#[doc(inline)]
pub use mysql_common::packets::{
    binlog_request::BinlogRequest,
    session_state_change::{
        Gtids, Schema, SessionStateChange, SystemVariable, TransactionCharacteristics,
        TransactionState, Unsupported,
    },
    BinlogDumpFlags, Column, Interval, OkPacket, SessionStateInfo, Sid,
};

pub mod binlog {
    #[doc(inline)]
    pub use mysql_common::binlog::consts::*;

    #[doc(inline)]
    pub use mysql_common::binlog::{events, jsonb, jsondiff, row, value};
}

#[doc(inline)]
pub use mysql_common::proto::codec::Compression;

#[doc(inline)]
pub use mysql_common::row::Row;

#[doc(inline)]
pub use mysql_common::params::Params;

#[doc(inline)]
pub use mysql_common::value::Value;

#[doc(inline)]
pub use mysql_common::row::convert::{from_row, from_row_opt, FromRowError};

#[doc(inline)]
pub use mysql_common::value::convert::{from_value, from_value_opt, FromValueError};

#[doc(inline)]
pub use mysql_common::value::json::{Deserialized, Serialized};

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

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

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

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

/// Futures used in this crate
pub mod futures {
    pub use crate::conn::pool::futures::{DisconnectPool, GetConn};
}

/// Traits used in this crate
pub mod prelude {
    #[doc(inline)]
    pub use crate::local_infile_handler::LocalInfileHandler;
    #[doc(inline)]
    pub use crate::query::{BatchQuery, Query, WithParams};
    #[doc(inline)]
    pub use crate::queryable::Queryable;
    #[doc(inline)]
    pub use mysql_common::row::convert::FromRow;
    #[doc(inline)]
    pub use mysql_common::value::convert::{ConvIr, FromValue, ToValue};

    /// Everything that is a statement.
    ///
    /// ```no_run
    /// # use std::{borrow::Cow, sync::Arc};
    /// # use mysql_async::{Statement, prelude::StatementLike};
    /// fn type_is_a_stmt<T: StatementLike>() {}
    ///
    /// type_is_a_stmt::<Cow<'_, str>>();
    /// type_is_a_stmt::<&'_ str>();
    /// type_is_a_stmt::<String>();
    /// type_is_a_stmt::<Box<str>>();
    /// type_is_a_stmt::<Arc<str>>();
    /// type_is_a_stmt::<Statement>();
    ///
    /// fn ref_to_a_clonable_stmt_is_also_a_stmt<T: StatementLike + Clone>() {
    ///     type_is_a_stmt::<&T>();
    /// }
    /// ```
    pub trait StatementLike: crate::queryable::stmt::StatementLike {}
    impl<T: crate::queryable::stmt::StatementLike> StatementLike for T {}

    /// Everything that is a connection.
    pub trait ToConnection<'a, 't: 'a>: crate::connection_like::ToConnection<'a, 't> {}
    // explicitly implemented because of rusdoc
    impl<'a> ToConnection<'a, 'static> for &'a crate::Pool {}
    impl ToConnection<'static, 'static> for crate::Conn {}
    impl<'a> ToConnection<'a, 'static> for &'a mut crate::Conn {}
    impl<'a, 't> ToConnection<'a, 't> for &'a mut crate::Transaction<'t> {}

    /// Trait for protocol markers [`crate::TextProtocol`] and [`crate::BinaryProtocol`].
    pub trait Protocol: crate::queryable::Protocol {}
    impl Protocol for crate::BinaryProtocol {}
    impl Protocol for crate::TextProtocol {}

    pub use mysql_common::params;
}

#[doc(hidden)]
pub mod test_misc {
    use lazy_static::lazy_static;

    use std::env;

    use crate::opts::{Opts, OptsBuilder, SslOpts};

    #[allow(dead_code)]
    fn error_should_implement_send_and_sync() {
        fn _dummy<T: Send + Sync>(_: T) {}
        _dummy(crate::error::Error::from("foo"));
    }

    lazy_static! {
        pub static ref DATABASE_URL: String = {
            if let Ok(url) = env::var("DATABASE_URL") {
                let opts = Opts::from_url(&url).expect("DATABASE_URL invalid");
                if opts
                    .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()
            }
        };
    }

    pub fn get_opts() -> OptsBuilder {
        let mut builder = OptsBuilder::from_opts(Opts::from_url(&**DATABASE_URL).unwrap());
        if test_ssl() {
            let ssl_opts = SslOpts::default()
                .with_danger_skip_domain_validation(true)
                .with_danger_accept_invalid_certs(true);
            builder = builder.prefer_socket(false).ssl_opts(ssl_opts);
        }
        if test_compression() {
            builder = builder.compression(crate::Compression::default());
        }
        builder
    }

    pub fn test_compression() -> bool {
        ["true", "1"].contains(&&*env::var("COMPRESS").unwrap_or_default())
    }

    pub fn test_ssl() -> bool {
        ["true", "1"].contains(&&*env::var("SSL").unwrap_or_default())
    }
}
<commit_msg>benches: remove const_fn feature<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_async = "<desired version>"
//! ```
//!
//! ### Example
//!
//! ```rust
//! # use mysql_async::{Result, test_misc::get_opts};
//! use mysql_async::prelude::*;
//! # use std::env;
//!
//! #[derive(Debug, PartialEq, Eq, Clone)]
//! struct Payment {
//!     customer_id: i32,
//!     amount: i32,
//!     account_name: Option<String>,
//! }
//!
//! #[tokio::main]
//! async fn main() -> Result<()> {
//!     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 = /* ... */
//!     # get_opts();
//!
//!     let pool = mysql_async::Pool::new(database_url);
//!     let mut conn = pool.get_conn().await?;
//!
//!     // Create temporary table
//!     conn.query_drop(
//!         r"CREATE TEMPORARY TABLE payment (
//!             customer_id int not null,
//!             amount int not null,
//!             account_name text
//!         )"
//!     ).await?;
//!
//!     // Save payments
//!     let params = payments.clone().into_iter().map(|payment| {
//!         params! {
//!             "customer_id" => payment.customer_id,
//!             "amount" => payment.amount,
//!             "account_name" => payment.account_name,
//!         }
//!     });
//!
//!     conn.exec_batch(
//!         r"INSERT INTO payment (customer_id, amount, account_name)
//!           VALUES (:customer_id, :amount, :account_name)",
//!         params,
//!     ).await?;
//!
//!     // Load payments from database. Type inference will work here.
//!     let loaded_payments = conn.exec_map(
//!         "SELECT customer_id, amount, account_name FROM payment",
//!         (),
//!         |(customer_id, amount, account_name)| Payment { customer_id, amount, account_name },
//!     ).await?;
//!
//!     // Dropped connection will go to the pool
//!     drop(conn);
//!
//!     // Pool must be disconnected explicitly because
//!     // it's an asynchronous operation.
//!     pool.disconnect().await?;
//!
//!     assert_eq!(loaded_payments, payments);
//!
//!     // the async fn returns Result, so
//!     Ok(())
//! }
//! ```

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

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

pub use mysql_common::{chrono, constants as consts, params, time, uuid};

use std::sync::Arc;

mod buffer_pool;

#[macro_use]
mod macros;
mod conn;
mod connection_like;
/// Errors used in this crate
mod error;
mod io;
mod local_infile_handler;
mod opts;
mod query;
mod queryable;

type BoxFuture<'a, T> = futures_core::future::BoxFuture<'a, Result<T>>;

static BUFFER_POOL: once_cell::sync::Lazy<Arc<crate::buffer_pool::BufferPool>> =
    once_cell::sync::Lazy::new(|| Default::default());

#[doc(inline)]
pub use self::conn::{binlog_stream::BinlogStream, Conn};

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

#[doc(inline)]
pub use self::error::{DriverError, Error, IoError, ParseError, Result, ServerError, UrlError};

#[doc(inline)]
pub use self::query::QueryWithParams;

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

#[doc(inline)]
pub use self::opts::{
    Opts, OptsBuilder, PoolConstraints, PoolOpts, SslOpts, DEFAULT_INACTIVE_CONNECTION_TTL,
    DEFAULT_POOL_CONSTRAINTS, DEFAULT_STMT_CACHE_SIZE, DEFAULT_TTL_CHECK_INTERVAL,
};

#[doc(inline)]
pub use self::local_infile_handler::{builtin::WhiteListFsLocalInfileHandler, InfileHandlerFuture};

#[doc(inline)]
pub use mysql_common::packets::{
    binlog_request::BinlogRequest,
    session_state_change::{
        Gtids, Schema, SessionStateChange, SystemVariable, TransactionCharacteristics,
        TransactionState, Unsupported,
    },
    BinlogDumpFlags, Column, Interval, OkPacket, SessionStateInfo, Sid,
};

pub mod binlog {
    #[doc(inline)]
    pub use mysql_common::binlog::consts::*;

    #[doc(inline)]
    pub use mysql_common::binlog::{events, jsonb, jsondiff, row, value};
}

#[doc(inline)]
pub use mysql_common::proto::codec::Compression;

#[doc(inline)]
pub use mysql_common::row::Row;

#[doc(inline)]
pub use mysql_common::params::Params;

#[doc(inline)]
pub use mysql_common::value::Value;

#[doc(inline)]
pub use mysql_common::row::convert::{from_row, from_row_opt, FromRowError};

#[doc(inline)]
pub use mysql_common::value::convert::{from_value, from_value_opt, FromValueError};

#[doc(inline)]
pub use mysql_common::value::json::{Deserialized, Serialized};

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

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

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

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

/// Futures used in this crate
pub mod futures {
    pub use crate::conn::pool::futures::{DisconnectPool, GetConn};
}

/// Traits used in this crate
pub mod prelude {
    #[doc(inline)]
    pub use crate::local_infile_handler::LocalInfileHandler;
    #[doc(inline)]
    pub use crate::query::{BatchQuery, Query, WithParams};
    #[doc(inline)]
    pub use crate::queryable::Queryable;
    #[doc(inline)]
    pub use mysql_common::row::convert::FromRow;
    #[doc(inline)]
    pub use mysql_common::value::convert::{ConvIr, FromValue, ToValue};

    /// Everything that is a statement.
    ///
    /// ```no_run
    /// # use std::{borrow::Cow, sync::Arc};
    /// # use mysql_async::{Statement, prelude::StatementLike};
    /// fn type_is_a_stmt<T: StatementLike>() {}
    ///
    /// type_is_a_stmt::<Cow<'_, str>>();
    /// type_is_a_stmt::<&'_ str>();
    /// type_is_a_stmt::<String>();
    /// type_is_a_stmt::<Box<str>>();
    /// type_is_a_stmt::<Arc<str>>();
    /// type_is_a_stmt::<Statement>();
    ///
    /// fn ref_to_a_clonable_stmt_is_also_a_stmt<T: StatementLike + Clone>() {
    ///     type_is_a_stmt::<&T>();
    /// }
    /// ```
    pub trait StatementLike: crate::queryable::stmt::StatementLike {}
    impl<T: crate::queryable::stmt::StatementLike> StatementLike for T {}

    /// Everything that is a connection.
    pub trait ToConnection<'a, 't: 'a>: crate::connection_like::ToConnection<'a, 't> {}
    // explicitly implemented because of rusdoc
    impl<'a> ToConnection<'a, 'static> for &'a crate::Pool {}
    impl ToConnection<'static, 'static> for crate::Conn {}
    impl<'a> ToConnection<'a, 'static> for &'a mut crate::Conn {}
    impl<'a, 't> ToConnection<'a, 't> for &'a mut crate::Transaction<'t> {}

    /// Trait for protocol markers [`crate::TextProtocol`] and [`crate::BinaryProtocol`].
    pub trait Protocol: crate::queryable::Protocol {}
    impl Protocol for crate::BinaryProtocol {}
    impl Protocol for crate::TextProtocol {}

    pub use mysql_common::params;
}

#[doc(hidden)]
pub mod test_misc {
    use lazy_static::lazy_static;

    use std::env;

    use crate::opts::{Opts, OptsBuilder, SslOpts};

    #[allow(dead_code)]
    fn error_should_implement_send_and_sync() {
        fn _dummy<T: Send + Sync>(_: T) {}
        _dummy(crate::error::Error::from("foo"));
    }

    lazy_static! {
        pub static ref DATABASE_URL: String = {
            if let Ok(url) = env::var("DATABASE_URL") {
                let opts = Opts::from_url(&url).expect("DATABASE_URL invalid");
                if opts
                    .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()
            }
        };
    }

    pub fn get_opts() -> OptsBuilder {
        let mut builder = OptsBuilder::from_opts(Opts::from_url(&**DATABASE_URL).unwrap());
        if test_ssl() {
            let ssl_opts = SslOpts::default()
                .with_danger_skip_domain_validation(true)
                .with_danger_accept_invalid_certs(true);
            builder = builder.prefer_socket(false).ssl_opts(ssl_opts);
        }
        if test_compression() {
            builder = builder.compression(crate::Compression::default());
        }
        builder
    }

    pub fn test_compression() -> bool {
        ["true", "1"].contains(&&*env::var("COMPRESS").unwrap_or_default())
    }

    pub fn test_ssl() -> bool {
        ["true", "1"].contains(&&*env::var("SSL").unwrap_or_default())
    }
}
<|endoftext|>


<commit_before>#![crate_name = "bindgen"]
#![crate_type = "dylib"]

#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]

// To avoid rather annoying warnings when matching with CXCursor_xxx as a
// constant.
#![allow(non_upper_case_globals)]

extern crate syntex_syntax as syntax;
extern crate aster;
extern crate quasi;
extern crate clang_sys;
extern crate libc;
extern crate regex;
#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;

mod clangll;
mod clang;
mod ir;
mod parse;
mod regex_set;
mod codegen {
    include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
}

use std::borrow::Borrow;
use std::io::{self, Write};
use std::fs::OpenOptions;
use std::path::Path;
use std::collections::HashSet;

use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::print::pprust;
use syntax::print::pp::eof;
use syntax::ptr::P;

use ir::context::BindgenContext;
use ir::item::{Item, ItemId};
use parse::{ClangItemParser, ParseError};
use regex_set::RegexSet;

#[derive(Debug,Default)]
pub struct Builder {
    options: BindgenOptions,
}

pub fn builder() -> Builder {
    Default::default()
}

impl Builder {
    pub fn header<T: Into<String>>(self, header: T) -> Builder {
        self.clang_arg(header)
    }

    pub fn hide_type<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.hidden_types.insert(arg.into());
        self
    }

    pub fn opaque_type<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.opaque_types.insert(arg.into());
        self
    }

    pub fn whitelisted_type<T: Borrow<str>>(mut self, arg: T) -> Builder {
        self.options.whitelisted_types.insert(&arg);
        self
    }

    pub fn whitelisted_function<T: Borrow<str>>(mut self, arg: T) -> Builder {
        self.options.whitelisted_functions.insert(&arg);
        self
    }

    pub fn whitelisted_var<T: Borrow<str>>(mut self, arg: T) -> Builder {
        self.options.whitelisted_vars.insert(&arg);
        self
    }

    pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.raw_lines.push(arg.into());
        self
    }

    pub fn clang_arg<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.clang_args.push(arg.into());
        self
    }

    pub fn link<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Default));
        self
    }

    pub fn link_static<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Static));
        self
    }

    pub fn link_framework<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Framework));
        self
    }

    pub fn emit_builtins(mut self) -> Builder {
        self.options.builtins = true;
        self
    }

    pub fn no_unstable_rust(mut self) -> Builder {
        self.options.unstable_rust = false;
        self
    }

    pub fn disable_class_constants(mut self) -> Builder {
        self.options.class_constants = false;
        self
    }

    pub fn generate(self) -> Result<Bindings, ()> {
        Bindings::generate(self.options, None)
    }
}

/// Deprecated - use a `Builder` instead
#[derive(Debug)]
pub struct BindgenOptions {
    pub hidden_types: HashSet<String>,
    pub opaque_types: HashSet<String>,
    pub whitelisted_types: RegexSet,
    pub whitelisted_functions: RegexSet,
    pub whitelisted_vars: RegexSet,
    pub builtins: bool,
    pub links: Vec<(String, LinkType)>,
    pub emit_ast: bool,
    pub ignore_functions: bool,
    pub ignore_methods: bool,
    pub enable_cxx_namespaces: bool,
    pub derive_debug: bool,
    /// Generate or not only stable rust.
    pub unstable_rust: bool,
    /// Whether to generate C++ class constants.
    pub class_constants: bool,
    /// Wether to generate names that are **directly** under namespaces.
    pub namespaced_constants: bool,
    /// Whether to use msvc mangling rules
    pub msvc_mangling: bool,
    pub override_enum_ty: String,
    pub raw_lines: Vec<String>,
    pub clang_args: Vec<String>,
}

impl Default for BindgenOptions {
    fn default() -> BindgenOptions {
        BindgenOptions {
            hidden_types: Default::default(),
            opaque_types: Default::default(),
            whitelisted_types: Default::default(),
            whitelisted_functions: Default::default(),
            whitelisted_vars: Default::default(),
            builtins: false,
            links: vec![],
            emit_ast: false,
            ignore_functions: false,
            ignore_methods: false,
            derive_debug: true,
            enable_cxx_namespaces: false,
            override_enum_ty: "".to_string(),
            unstable_rust: true,
            class_constants: true,
            namespaced_constants: true,
            msvc_mangling: false,
            raw_lines: vec![],
            clang_args: vec![],
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum LinkType {
    Default,
    Static,
    Framework
}

#[derive(Debug, Clone)]
pub struct Bindings {
    module: ast::Mod,
    raw_lines: Vec<String>,
}

impl Bindings {
    /// Deprecated - use a `Builder` instead
    pub fn generate(options: BindgenOptions, span: Option<Span>) -> Result<Bindings, ()> {
        let span = span.unwrap_or(DUMMY_SP);

        let mut context = BindgenContext::new(options);
        parse(&mut context);

        let module = ast::Mod {
            inner: span,
            items: codegen::codegen(&mut context),
        };

        Ok(Bindings {
            module: module,
            raw_lines: context.options().raw_lines.clone(),
        })
    }

    pub fn into_ast(self) -> Vec<P<ast::Item>> {
        self.module.items
    }

    pub fn to_string(&self) -> String {
        let mut mod_str = vec![];
        {
            let ref_writer = Box::new(mod_str.by_ref()) as Box<Write>;
            self.write(ref_writer).expect("Could not write bindings to string");
        }
        String::from_utf8(mod_str).unwrap()
    }

    pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
        let file = try!(OpenOptions::new().write(true).truncate(true).create(true).open(path));
        self.write(Box::new(file))
    }

    // https://github.com/Manishearth/rust-clippy/issues/740
    #[cfg_attr(feature = "clippy", allow(needless_lifetimes))]
    pub fn write<'a>(&self, mut writer: Box<Write + 'a>) -> io::Result<()> {
        try!(writer.write("/* automatically generated by rust-bindgen */\n\n".as_bytes()));

        for line in self.raw_lines.iter() {
            try!(writer.write(line.as_bytes()));
            try!(writer.write("\n".as_bytes()));
        }
        if !self.raw_lines.is_empty() {
            try!(writer.write("\n".as_bytes()));
        }

        let mut ps = pprust::rust_printer(writer);
        try!(ps.print_mod(&self.module, &[]));
        try!(ps.print_remaining_comments());
        try!(eof(&mut ps.s));
        ps.s.out.flush()
    }
}

/// Determines whether the given cursor is in any of the files matched by the
/// options.
fn filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool {
    let (file, _, _, _) = cursor.location().location();

    match file.name() {
        None => ctx.options().builtins,
        Some(..) => true,
    }
}

pub fn parse_one(ctx: &mut BindgenContext,
                 cursor: clang::Cursor,
                 parent: Option<ItemId>,
                 children: &mut Vec<ItemId>) -> clangll::Enum_CXVisitorResult {
    if !filter_builtins(ctx, &cursor) {
        return CXChildVisit_Continue
    }

    use clangll::CXChildVisit_Continue;
    match Item::parse(cursor, parent, ctx) {
        Ok(id) => children.push(id),
        Err(ParseError::Continue) => {},
        Err(ParseError::Recurse) => {
            cursor.visit(|child, _| parse_one(ctx, *child, parent, children));
        }
    }
    CXChildVisit_Continue
}

fn parse(context: &mut BindgenContext) {
    use clang::Diagnostic;
    use clangll::*;

    for d in context.translation_unit().diags().iter() {
        let msg = d.format(Diagnostic::default_opts());
        let is_err = d.severity() >= CXDiagnostic_Error;
        println!("{}, err: {}", msg, is_err);
    }

    let cursor = context.translation_unit().cursor();
    if context.options().emit_ast {
        cursor.visit(|cur, _| clang::ast_dump(cur, 0));
    }

    let root = context.root_module();
    context.with_module(root, |context, children| {
        cursor.visit(|cursor, _| parse_one(context, *cursor, None, children))
    });

    assert!(context.current_module() == context.root_module(),
            "How did this happen?");
}
<commit_msg>Remove the unused class_constants option<commit_after>#![crate_name = "bindgen"]
#![crate_type = "dylib"]

#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]

// To avoid rather annoying warnings when matching with CXCursor_xxx as a
// constant.
#![allow(non_upper_case_globals)]

extern crate syntex_syntax as syntax;
extern crate aster;
extern crate quasi;
extern crate clang_sys;
extern crate libc;
extern crate regex;
#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;

mod clangll;
mod clang;
mod ir;
mod parse;
mod regex_set;
mod codegen {
    include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
}

use std::borrow::Borrow;
use std::io::{self, Write};
use std::fs::OpenOptions;
use std::path::Path;
use std::collections::HashSet;

use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::print::pprust;
use syntax::print::pp::eof;
use syntax::ptr::P;

use ir::context::BindgenContext;
use ir::item::{Item, ItemId};
use parse::{ClangItemParser, ParseError};
use regex_set::RegexSet;

#[derive(Debug,Default)]
pub struct Builder {
    options: BindgenOptions,
}

pub fn builder() -> Builder {
    Default::default()
}

impl Builder {
    pub fn header<T: Into<String>>(self, header: T) -> Builder {
        self.clang_arg(header)
    }

    pub fn hide_type<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.hidden_types.insert(arg.into());
        self
    }

    pub fn opaque_type<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.opaque_types.insert(arg.into());
        self
    }

    pub fn whitelisted_type<T: Borrow<str>>(mut self, arg: T) -> Builder {
        self.options.whitelisted_types.insert(&arg);
        self
    }

    pub fn whitelisted_function<T: Borrow<str>>(mut self, arg: T) -> Builder {
        self.options.whitelisted_functions.insert(&arg);
        self
    }

    pub fn whitelisted_var<T: Borrow<str>>(mut self, arg: T) -> Builder {
        self.options.whitelisted_vars.insert(&arg);
        self
    }

    pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.raw_lines.push(arg.into());
        self
    }

    pub fn clang_arg<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.clang_args.push(arg.into());
        self
    }

    pub fn link<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Default));
        self
    }

    pub fn link_static<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Static));
        self
    }

    pub fn link_framework<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Framework));
        self
    }

    pub fn emit_builtins(mut self) -> Builder {
        self.options.builtins = true;
        self
    }

    pub fn no_unstable_rust(mut self) -> Builder {
        self.options.unstable_rust = false;
        self
    }

    pub fn generate(self) -> Result<Bindings, ()> {
        Bindings::generate(self.options, None)
    }
}

/// Deprecated - use a `Builder` instead
#[derive(Debug)]
pub struct BindgenOptions {
    pub hidden_types: HashSet<String>,
    pub opaque_types: HashSet<String>,
    pub whitelisted_types: RegexSet,
    pub whitelisted_functions: RegexSet,
    pub whitelisted_vars: RegexSet,
    pub builtins: bool,
    pub links: Vec<(String, LinkType)>,
    pub emit_ast: bool,
    pub ignore_functions: bool,
    pub ignore_methods: bool,
    pub enable_cxx_namespaces: bool,
    pub derive_debug: bool,
    /// Generate or not only stable rust.
    pub unstable_rust: bool,
    /// Wether to generate names that are **directly** under namespaces.
    pub namespaced_constants: bool,
    /// Whether to use msvc mangling rules
    pub msvc_mangling: bool,
    pub override_enum_ty: String,
    pub raw_lines: Vec<String>,
    pub clang_args: Vec<String>,
}

impl Default for BindgenOptions {
    fn default() -> BindgenOptions {
        BindgenOptions {
            hidden_types: Default::default(),
            opaque_types: Default::default(),
            whitelisted_types: Default::default(),
            whitelisted_functions: Default::default(),
            whitelisted_vars: Default::default(),
            builtins: false,
            links: vec![],
            emit_ast: false,
            ignore_functions: false,
            ignore_methods: false,
            derive_debug: true,
            enable_cxx_namespaces: false,
            override_enum_ty: "".to_string(),
            unstable_rust: true,
            namespaced_constants: true,
            msvc_mangling: false,
            raw_lines: vec![],
            clang_args: vec![],
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum LinkType {
    Default,
    Static,
    Framework
}

#[derive(Debug, Clone)]
pub struct Bindings {
    module: ast::Mod,
    raw_lines: Vec<String>,
}

impl Bindings {
    /// Deprecated - use a `Builder` instead
    pub fn generate(options: BindgenOptions, span: Option<Span>) -> Result<Bindings, ()> {
        let span = span.unwrap_or(DUMMY_SP);

        let mut context = BindgenContext::new(options);
        parse(&mut context);

        let module = ast::Mod {
            inner: span,
            items: codegen::codegen(&mut context),
        };

        Ok(Bindings {
            module: module,
            raw_lines: context.options().raw_lines.clone(),
        })
    }

    pub fn into_ast(self) -> Vec<P<ast::Item>> {
        self.module.items
    }

    pub fn to_string(&self) -> String {
        let mut mod_str = vec![];
        {
            let ref_writer = Box::new(mod_str.by_ref()) as Box<Write>;
            self.write(ref_writer).expect("Could not write bindings to string");
        }
        String::from_utf8(mod_str).unwrap()
    }

    pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
        let file = try!(OpenOptions::new().write(true).truncate(true).create(true).open(path));
        self.write(Box::new(file))
    }

    // https://github.com/Manishearth/rust-clippy/issues/740
    #[cfg_attr(feature = "clippy", allow(needless_lifetimes))]
    pub fn write<'a>(&self, mut writer: Box<Write + 'a>) -> io::Result<()> {
        try!(writer.write("/* automatically generated by rust-bindgen */\n\n".as_bytes()));

        for line in self.raw_lines.iter() {
            try!(writer.write(line.as_bytes()));
            try!(writer.write("\n".as_bytes()));
        }
        if !self.raw_lines.is_empty() {
            try!(writer.write("\n".as_bytes()));
        }

        let mut ps = pprust::rust_printer(writer);
        try!(ps.print_mod(&self.module, &[]));
        try!(ps.print_remaining_comments());
        try!(eof(&mut ps.s));
        ps.s.out.flush()
    }
}

/// Determines whether the given cursor is in any of the files matched by the
/// options.
fn filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool {
    let (file, _, _, _) = cursor.location().location();

    match file.name() {
        None => ctx.options().builtins,
        Some(..) => true,
    }
}

pub fn parse_one(ctx: &mut BindgenContext,
                 cursor: clang::Cursor,
                 parent: Option<ItemId>,
                 children: &mut Vec<ItemId>) -> clangll::Enum_CXVisitorResult {
    if !filter_builtins(ctx, &cursor) {
        return CXChildVisit_Continue
    }

    use clangll::CXChildVisit_Continue;
    match Item::parse(cursor, parent, ctx) {
        Ok(id) => children.push(id),
        Err(ParseError::Continue) => {},
        Err(ParseError::Recurse) => {
            cursor.visit(|child, _| parse_one(ctx, *child, parent, children));
        }
    }
    CXChildVisit_Continue
}

fn parse(context: &mut BindgenContext) {
    use clang::Diagnostic;
    use clangll::*;

    for d in context.translation_unit().diags().iter() {
        let msg = d.format(Diagnostic::default_opts());
        let is_err = d.severity() >= CXDiagnostic_Error;
        println!("{}, err: {}", msg, is_err);
    }

    let cursor = context.translation_unit().cursor();
    if context.options().emit_ast {
        cursor.visit(|cur, _| clang::ast_dump(cur, 0));
    }

    let root = context.root_module();
    context.with_module(root, |context, children| {
        cursor.visit(|cursor, _| parse_one(context, *cursor, None, children))
    });

    assert!(context.current_module() == context.root_module(),
            "How did this happen?");
}
<|endoftext|>