<commit_before>//! A crate which exports rays, axis-aligned bounding boxes, and binary bounding
//! volume hierarchies.
//!
//! ## About
//!
//! This crate can be used for applications which contain intersection computations of rays
//! with primitives. For this purpose a binary tree BVH (Bounding Volume Hierarchy) is of great
//! use if the scene which the ray traverses contains a huge number of primitives. With a BVH the
//! intersection test complexity is reduced from O(n) to O(log2(n)) at the cost of building
//! the BVH once in advance. This technique is especially useful in ray/path tracers. For
//! use in a shader this module also exports a flattening procedure, which allows for
//! iterative traversal of the BVH.
//!
//! ## Example
//!
//! ```
//! use bvh::aabb::{AABB, Bounded};
//! use bvh::bounding_hierarchy::{BoundingHierarchy, BHShape};
//! use bvh::bvh::BVH;
//! use bvh::{Point3, Vector3};
//! use bvh::ray::Ray;
//!
//! let origin = Point3::new(0.0,0.0,0.0);
//! let direction = Vector3::new(1.0,0.0,0.0);
//! let ray = Ray::new(origin, direction);
//!
//! struct Sphere {
//!     position: Point3,
//!     radius: f32,
//!     node_index: usize,
//! }
//!
//! impl Bounded for Sphere {
//!     fn aabb(&self) -> AABB {
//!         let half_size = Vector3::new(self.radius, self.radius, self.radius);
//!         let min = self.position - half_size;
//!         let max = self.position + half_size;
//!         AABB::with_bounds(min, max)
//!     }
//! }
//!
//! impl BHShape for Sphere {
//!     fn set_bh_node_index(&mut self, index: usize) {
//!         self.node_index = index;
//!     }
//!
//!     fn bh_node_index(&self) -> usize {
//!         self.node_index
//!     }
//! }
//!
//! let mut spheres = Vec::new();
//! for i in 0..1000u32 {
//!     let position = Point3::new(i as f32, i as f32, i as f32);
//!     let radius = (i % 10) as f32 + 1.0;
//!     spheres.push(Sphere {
//!         position: position,
//!         radius: radius,
//!         node_index: 0,
//!     });
//! }
//!
//! let bvh = BVH::build(&mut spheres);
//! let hit_sphere_aabbs = bvh.traverse(&ray, &spheres);
//! ```
//!
//! ## Features
//!
//! - `serde_impls` (default **disabled**) - adds `Serialize` and `Deserialize` implementations for some types
//!

#![deny(missing_docs)]
#![cfg_attr(feature = "bench", feature(test))]

#[cfg(all(feature = "bench", test))]
extern crate test;

/// A minimal floating value used as a lower bound.
/// TODO: replace by/add ULPS/relative float comparison methods.
pub const EPSILON: f32 = 0.00001;

/// Point math type used by this crate. Type alias for [`glam::Vec3`].
pub type Point3 = glam::Vec3;

/// Vector math type used by this crate. Type alias for [`glam::Vec3`].
pub type Vector3 = glam::Vec3;

pub mod aabb;
pub mod axis;
pub mod bounding_hierarchy;
pub mod bvh;
pub mod flat_bvh;
pub mod ray;
mod utils;

#[cfg(test)]
mod testbase;
<commit_msg>Remove useless BoundingHierarchy import in lib.rs docs.<commit_after>//! A crate which exports rays, axis-aligned bounding boxes, and binary bounding
//! volume hierarchies.
//!
//! ## About
//!
//! This crate can be used for applications which contain intersection computations of rays
//! with primitives. For this purpose a binary tree BVH (Bounding Volume Hierarchy) is of great
//! use if the scene which the ray traverses contains a huge number of primitives. With a BVH the
//! intersection test complexity is reduced from O(n) to O(log2(n)) at the cost of building
//! the BVH once in advance. This technique is especially useful in ray/path tracers. For
//! use in a shader this module also exports a flattening procedure, which allows for
//! iterative traversal of the BVH.
//!
//! ## Example
//!
//! ```
//! use bvh::aabb::{AABB, Bounded};
//! use bvh::bounding_hierarchy::BHShape;
//! use bvh::bvh::BVH;
//! use bvh::{Point3, Vector3};
//! use bvh::ray::Ray;
//!
//! let origin = Point3::new(0.0,0.0,0.0);
//! let direction = Vector3::new(1.0,0.0,0.0);
//! let ray = Ray::new(origin, direction);
//!
//! struct Sphere {
//!     position: Point3,
//!     radius: f32,
//!     node_index: usize,
//! }
//!
//! impl Bounded for Sphere {
//!     fn aabb(&self) -> AABB {
//!         let half_size = Vector3::new(self.radius, self.radius, self.radius);
//!         let min = self.position - half_size;
//!         let max = self.position + half_size;
//!         AABB::with_bounds(min, max)
//!     }
//! }
//!
//! impl BHShape for Sphere {
//!     fn set_bh_node_index(&mut self, index: usize) {
//!         self.node_index = index;
//!     }
//!
//!     fn bh_node_index(&self) -> usize {
//!         self.node_index
//!     }
//! }
//!
//! let mut spheres = Vec::new();
//! for i in 0..1000u32 {
//!     let position = Point3::new(i as f32, i as f32, i as f32);
//!     let radius = (i % 10) as f32 + 1.0;
//!     spheres.push(Sphere {
//!         position: position,
//!         radius: radius,
//!         node_index: 0,
//!     });
//! }
//!
//! let bvh = BVH::build(&mut spheres);
//! let hit_sphere_aabbs = bvh.traverse(&ray, &spheres);
//! ```
//!
//! ## Features
//!
//! - `serde_impls` (default **disabled**) - adds `Serialize` and `Deserialize` implementations for some types
//!

#![deny(missing_docs)]
#![cfg_attr(feature = "bench", feature(test))]

#[cfg(all(feature = "bench", test))]
extern crate test;

/// A minimal floating value used as a lower bound.
/// TODO: replace by/add ULPS/relative float comparison methods.
pub const EPSILON: f32 = 0.00001;

/// Point math type used by this crate. Type alias for [`glam::Vec3`].
pub type Point3 = glam::Vec3;

/// Vector math type used by this crate. Type alias for [`glam::Vec3`].
pub type Vector3 = glam::Vec3;

pub mod aabb;
pub mod axis;
pub mod bounding_hierarchy;
pub mod bvh;
pub mod flat_bvh;
pub mod ray;
mod utils;

#[cfg(test)]
mod testbase;
<|endoftext|>


<commit_before>pub fn compile(sass: String, style: &str) -> String {
    match style {
        "nested"     => nested(sass),
        "compressed" => compressed(sass),
        "expanded"   => expanded(sass),
        "compact"    => compact(sass),
        _            => panic!("Unknown style: {}. Please specify one of nested, compressed, expanded, or compact.", style),
    }
}

fn nested(sass: String) -> String {
    sass
}

fn compressed(sass: String) -> String {
    sass.replace(" ", "").replace("\n", "")
}

fn expanded(sass: String) -> String {
    sass
}

fn compact(sass: String) -> String {
    sass
}
<commit_msg>Start of a parser<commit_after>pub fn compile(sass: String, style: &str) -> String {
    let parsed = SassReader::new(sass).parse();
    match style {
        "nested"     => nested(parsed),
        "compressed" => compressed(parsed),
        "expanded"   => expanded(parsed),
        "compact"    => compact(parsed),
        _            => panic!("Unknown style: {}. Please specify one of nested, compressed, expanded, or compact.", style),
    }
}

fn nested(sass: String) -> String {
    sass
}

fn compressed(sass: String) -> String {
    sass.replace(" ", "").replace("\n", "")
}

fn expanded(sass: String) -> String {
    sass
}

fn compact(sass: String) -> String {
    sass
}

struct SassReader {
    pub pos: u32,
    pub last_pos: u32,
    pub curr: Option<char>,
    sass: String,
}

impl SassReader {
    pub fn new(str: String) -> SassReader {
        SassReader {
            pos: 0,
            last_pos: 0,
            curr: Some('\n'),
            sass: str,
        }
    }

    pub fn parse(self) -> String {
        self.sass
    }
}<|endoftext|>


<commit_before>//! `bincode` is a crate for encoding and decoding using a tiny binary
//! serialization strategy.
//!
//! There are simple functions for encoding to `Vec<u8>` and decoding from
//! `&[u8]`, but the meat of the library is the `encode_into` and `decode_from`
//! functions which respectively allow encoding into a `std::io::Writer`
//! and decoding from a `std::io::Buffer`.
//!
//! ## Modules
//! There are two ways to encode and decode structs using `bincode`, either using `rustc_serialize`
//! or the `serde` crate.  `rustc_serialize` and `serde` are crates and and also the names of their
//! corresponding modules inside of `bincode`.  Both modules have exactly equivalant functions, and
//! and the only difference is whether or not the library user wants to use `rustc_serialize` or
//! `serde`.
//!
//! ### Using Basic Functions
//!
//! ```rust
//! extern crate bincode;
//! use bincode::{serialize, deserialize};
//! fn main() {
//!     // The object that we will serialize.
//!     let target = Some("hello world".to_string());
//!     // The maximum size of the encoded message.
//!     let limit = bincode::SizeLimit::Bounded(20);
//!
//!     let encoded: Vec<u8>        = serialize(&target, limit).unwrap();
//!     let decoded: Option<String> = deserialize(&encoded[..]).unwrap();
//!     assert_eq!(target, decoded);
//! }
//! ```

#![crate_name = "bincode"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]

#![doc(html_logo_url = "./icon.png")]

extern crate byteorder;
extern crate num_traits;
extern crate serde as serde_crate;

pub mod refbox;
mod serde;

pub mod endian_choice {
    pub use super::serde::{serialize, serialize_into, deserialize, deserialize_from};
}

use std::io::{Read, Write};

pub use serde::{Deserializer, Serializer, ErrorKind, Error, Result, serialized_size, serialized_size_bounded};

/// Deserializes a slice of bytes into an object.
///
/// This method does not have a size-limit because if you already have the bytes
/// in memory, then you don't gain anything by having a limiter.
pub fn deserialize<T>(bytes: &[u8]) -> serde::Result<T>
    where T: serde_crate::Deserialize,
{
    serde::deserialize::<_, byteorder::LittleEndian>(bytes)
}

/// Deserializes an object directly from a `Buffer`ed Reader.
///
/// If the provided `SizeLimit` is reached, the deserialization will bail immediately.
/// A SizeLimit can help prevent an attacker from flooding your server with
/// a neverending stream of values that runs your server out of memory.
///
/// If this returns an `Error`, assume that the buffer that you passed
/// in is in an invalid state, as the error could be returned during any point
/// in the reading.
pub fn deserialize_from<R: ?Sized, T>(reader: &mut R, size_limit: SizeLimit) -> serde::Result<T>
    where R: Read,
          T: serde_crate::Deserialize,
{
    serde::deserialize_from::<_, _, byteorder::LittleEndian>(reader, size_limit)
}

/// Serializes an object directly into a `Writer`.
///
/// If the serialization would take more bytes than allowed by `size_limit`, an error
/// is returned and *no bytes* will be written into the `Writer`.
///
/// If this returns an `Error` (other than SizeLimit), assume that the
/// writer is in an invalid state, as writing could bail out in the middle of
/// serializing.
pub fn serialize_into<W: ?Sized, T: ?Sized>(writer: &mut W, value: &T, size_limit: SizeLimit) -> serde::Result<()>
    where W: Write, T: serde_crate::Serialize
{
    serde::serialize_into::<_, _, byteorder::LittleEndian>(writer, value, size_limit)
}

/// Serializes a serializable object into a `Vec` of bytes.
///
/// If the serialization would take more bytes than allowed by `size_limit`,
/// an error is returned.
pub fn serialize<T: ?Sized>(value: &T, size_limit: SizeLimit) -> serde::Result<Vec<u8>>
    where T: serde_crate::Serialize
{
    serde::serialize::<_, byteorder::LittleEndian>(value, size_limit)
}

/// A limit on the amount of bytes that can be read or written.
///
/// Size limits are an incredibly important part of both encoding and decoding.
///
/// In order to prevent DOS attacks on a decoder, it is important to limit the
/// amount of bytes that a single encoded message can be; otherwise, if you
/// are decoding bytes right off of a TCP stream for example, it would be
/// possible for an attacker to flood your server with a 3TB vec, causing the
/// decoder to run out of memory and crash your application!
/// Because of this, you can provide a maximum-number-of-bytes that can be read
/// during decoding, and the decoder will explicitly fail if it has to read
/// any more than that.
///
/// On the other side, you want to make sure that you aren't encoding a message
/// that is larger than your decoder expects.  By supplying a size limit to an
/// encoding function, the encoder will verify that the structure can be encoded
/// within that limit.  This verification occurs before any bytes are written to
/// the Writer, so recovering from an error is easy.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub enum SizeLimit {
    Infinite,
    Bounded(u64)
}
<commit_msg>Fix unintentional breaking API change in `Serializer`/`Deserializer` (#128)<commit_after>//! `bincode` is a crate for encoding and decoding using a tiny binary
//! serialization strategy.
//!
//! There are simple functions for encoding to `Vec<u8>` and decoding from
//! `&[u8]`, but the meat of the library is the `encode_into` and `decode_from`
//! functions which respectively allow encoding into a `std::io::Writer`
//! and decoding from a `std::io::Buffer`.
//!
//! ## Modules
//! There are two ways to encode and decode structs using `bincode`, either using `rustc_serialize`
//! or the `serde` crate.  `rustc_serialize` and `serde` are crates and and also the names of their
//! corresponding modules inside of `bincode`.  Both modules have exactly equivalant functions, and
//! and the only difference is whether or not the library user wants to use `rustc_serialize` or
//! `serde`.
//!
//! ### Using Basic Functions
//!
//! ```rust
//! extern crate bincode;
//! use bincode::{serialize, deserialize};
//! fn main() {
//!     // The object that we will serialize.
//!     let target = Some("hello world".to_string());
//!     // The maximum size of the encoded message.
//!     let limit = bincode::SizeLimit::Bounded(20);
//!
//!     let encoded: Vec<u8>        = serialize(&target, limit).unwrap();
//!     let decoded: Option<String> = deserialize(&encoded[..]).unwrap();
//!     assert_eq!(target, decoded);
//! }
//! ```

#![crate_name = "bincode"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]

#![doc(html_logo_url = "./icon.png")]

extern crate byteorder;
extern crate num_traits;
extern crate serde as serde_crate;

pub mod refbox;
mod serde;

pub mod endian_choice {
    pub use super::serde::{Deserializer, Serializer, serialize, serialize_into, deserialize, deserialize_from};
}

use std::io::{Read, Write};

pub use serde::{ErrorKind, Error, Result, serialized_size, serialized_size_bounded};

pub type Deserializer<W> = serde::Deserializer<W, byteorder::LittleEndian>;
pub type Serializer<W> = serde::Serializer<W, byteorder::LittleEndian>;

/// Deserializes a slice of bytes into an object.
///
/// This method does not have a size-limit because if you already have the bytes
/// in memory, then you don't gain anything by having a limiter.
pub fn deserialize<T>(bytes: &[u8]) -> serde::Result<T>
    where T: serde_crate::Deserialize,
{
    serde::deserialize::<_, byteorder::LittleEndian>(bytes)
}

/// Deserializes an object directly from a `Buffer`ed Reader.
///
/// If the provided `SizeLimit` is reached, the deserialization will bail immediately.
/// A SizeLimit can help prevent an attacker from flooding your server with
/// a neverending stream of values that runs your server out of memory.
///
/// If this returns an `Error`, assume that the buffer that you passed
/// in is in an invalid state, as the error could be returned during any point
/// in the reading.
pub fn deserialize_from<R: ?Sized, T>(reader: &mut R, size_limit: SizeLimit) -> serde::Result<T>
    where R: Read,
          T: serde_crate::Deserialize,
{
    serde::deserialize_from::<_, _, byteorder::LittleEndian>(reader, size_limit)
}

/// Serializes an object directly into a `Writer`.
///
/// If the serialization would take more bytes than allowed by `size_limit`, an error
/// is returned and *no bytes* will be written into the `Writer`.
///
/// If this returns an `Error` (other than SizeLimit), assume that the
/// writer is in an invalid state, as writing could bail out in the middle of
/// serializing.
pub fn serialize_into<W: ?Sized, T: ?Sized>(writer: &mut W, value: &T, size_limit: SizeLimit) -> serde::Result<()>
    where W: Write, T: serde_crate::Serialize
{
    serde::serialize_into::<_, _, byteorder::LittleEndian>(writer, value, size_limit)
}

/// Serializes a serializable object into a `Vec` of bytes.
///
/// If the serialization would take more bytes than allowed by `size_limit`,
/// an error is returned.
pub fn serialize<T: ?Sized>(value: &T, size_limit: SizeLimit) -> serde::Result<Vec<u8>>
    where T: serde_crate::Serialize
{
    serde::serialize::<_, byteorder::LittleEndian>(value, size_limit)
}

/// A limit on the amount of bytes that can be read or written.
///
/// Size limits are an incredibly important part of both encoding and decoding.
///
/// In order to prevent DOS attacks on a decoder, it is important to limit the
/// amount of bytes that a single encoded message can be; otherwise, if you
/// are decoding bytes right off of a TCP stream for example, it would be
/// possible for an attacker to flood your server with a 3TB vec, causing the
/// decoder to run out of memory and crash your application!
/// Because of this, you can provide a maximum-number-of-bytes that can be read
/// during decoding, and the decoder will explicitly fail if it has to read
/// any more than that.
///
/// On the other side, you want to make sure that you aren't encoding a message
/// that is larger than your decoder expects.  By supplying a size limit to an
/// encoding function, the encoder will verify that the structure can be encoded
/// within that limit.  This verification occurs before any bytes are written to
/// the Writer, so recovering from an error is easy.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub enum SizeLimit {
    Infinite,
    Bounded(u64)
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]
#![feature(unsafe_destructor)]

//! A library for setting current values for stack scope,
//! such as application structure.

pub use current::{ Current, CurrentGuard };

use std::cell::RefCell;

mod current;

/// Used as warning sign for functions
/// that under normal circumstances works with safe code,
/// but in some edge cases are unsafe.
///
/// 1. The function MUST take `DANGER` as first argument.
///
/// 2. The function MUST take ownership of the value.
///
/// 3. The function docs MUST include a notice `### DANGER`
/// describing the edge case.
///
/// It can not be copied, so an unsafe block is required
/// whenever it is used.
#[allow(missing_copy_implementations)]
pub struct DANGER(());

impl DANGER {
    /// Creates a new warning sign for functions
    /// that normally works with safe code
    pub unsafe fn new() -> DANGER { DANGER(()) }
}

impl<F: 'static, T: Modifier<F>> Modifier<Current<F>> for T {
    #[inline(always)]
    fn modify(self, obj: &mut Current<F>) {
        self.modify((*obj).deref_mut());
    }
}

impl<T: 'static + Get<U>, U> Get<U> for Current<T> {
    #[inline(always)]
    fn get(&self) -> U {
        (*self).deref().get()
    }
}

impl<'a, T: Get<U>, U> Get<U> for &'a RefCell<T> {
    #[inline(always)]
    fn get(&self) -> U {
        self.borrow().deref().get()
    }
}

impl<'a, F, T: Modifier<F>> Modifier<&'a RefCell<F>> for T {
    #[inline(always)]
    fn modify(self, obj: &mut &'a RefCell<F>) {
        self.modify(obj.borrow_mut().deref_mut())
    }
}

/// Allows use of the implemented type as an argument to Set::set.
///
/// This allows types to be used for ad-hoc overloading of Set::set
/// to perform complex updates to the parameter of Modifier.
pub trait Modifier<F> {
    /// Modify `F` with self.
    fn modify(self, &mut F);
}

/// A blanket trait providing the set and set_mut methods for all types.
pub trait Set<M> {
    /// Modify self using the provided modifier.
    fn set(mut self, modifier: M) -> Self;

    /// Modify self through a mutable reference with the provided modifier.
    fn set_mut(&mut self, modifier: M) -> &mut Self;
}

impl<T, U: Modifier<T>> Set<U> for T {
    #[inline(always)]
    fn set(mut self, modifier: U) -> T {
        modifier.modify(&mut self);
        self
    }

    #[inline(always)]
    fn set_mut(&mut self, modifier: U) -> &mut T {
        modifier.modify(self);
        self
    }
}

/// Implemented by types that can be constructed from another value.
pub trait Get<T> {
    /// Returns new value.
    fn get(&self) -> T;
}
<commit_msg>Redesign<commit_after>#![deny(missing_docs)]
#![feature(unsafe_destructor)]

//! A library for setting current values for stack scope,
//! such as application structure.

pub use current::{ Current, CurrentGuard };

use std::cell::RefCell;

mod current;

/// Used as warning sign for functions
/// that under normal circumstances works with safe code,
/// but in some edge cases are unsafe.
///
/// 1. The function MUST take `DANGER` as first argument.
///
/// 2. The function MUST take ownership of the value.
///
/// 3. The function docs MUST include a notice `### DANGER`
/// describing the edge case.
///
/// It can not be copied, so an unsafe block is required
/// whenever it is used.
#[allow(missing_copy_implementations)]
pub struct DANGER(());

impl DANGER {
    /// Creates a new warning sign for functions
    /// that normally works with safe code
    pub unsafe fn new() -> DANGER { DANGER(()) }
}

impl<F: 'static, T: SetAt<F>> SetAt<Current<F>> for T {
    #[inline(always)]
    fn set_at(self, obj: &mut Current<F>) {
        self.set_at((*obj).deref_mut());
    }
}

impl<F: 'static, T: ActOn<F, U>, U> ActOn<Current<F>, U> for T {
    #[inline(always)]
    fn act_on(self, obj: &mut Current<F>) -> U {
        self.act_on((*obj).deref_mut())
    }
}

impl<T: 'static, U: GetFrom<T>> GetFrom<Current<T>> for U {
    #[inline(always)]
    fn get_from(obj: &Current<T>) -> U {
        GetFrom::get_from((*obj).deref())
    }
}

impl<'a, T, U: GetFrom<T>> GetFrom<&'a RefCell<T>> for U {
    #[inline(always)]
    fn get_from(obj: & &'a RefCell<T>) -> U {
        GetFrom::get_from(obj.borrow().deref())
    }
}

impl<'a, F, T: SetAt<F>> SetAt<&'a RefCell<F>> for T {
    #[inline(always)]
    fn set_at(self, obj: &mut &'a RefCell<F>) {
        self.set_at(obj.borrow_mut().deref_mut())
    }
}

impl<'a, F, T: ActOn<F, U>, U> ActOn<&'a RefCell<F>, U> for T {
    #[inline(always)]
    fn act_on(self, obj: &mut &'a RefCell<F>) -> U {
        self.act_on(obj.borrow_mut().deref_mut())
    }
}

/// Something that can be set at an object.
pub trait SetAt<F> {
    /// Modify `F` with self.
    fn set_at(self, &mut F);
}

/// Automatically implemented through the `SetAt` trait.
pub trait Set<T> {
    /// Set value.
    fn set(mut self, val: T) -> Self;

    /// Set value through mutable reference.
    fn set_mut(&mut self, val: T) -> &mut Self;
}

impl<T, U: SetAt<T>> Set<U> for T {
    #[inline(always)]
    fn set(mut self, val: U) -> T {
        val.set_at(&mut self);
        self
    }

    #[inline(always)]
    fn set_mut(&mut self, val: U) -> &mut T {
        val.set_at(self);
        self
    }
}

/// Something that can be retrieved from another object.
pub trait GetFrom<T> {
    /// Gets value from object.
    fn get_from(obj: &T) -> Self;
}

/// Automatically implemented through the `GetFrom` trait.
pub trait Get<T> {
    /// Returns new value.
    fn get(&self) -> T;
}

impl<T, U: GetFrom<T>> Get<U> for T {
    #[inline(always)]
    fn get(&self) -> U {
        GetFrom::get_from(self)
    }
}

/// Does something to an object.
pub trait ActOn<T, U> {
    /// Does something to an object.
    fn act_on(self, &mut T) -> U;
}

/// Automatically implemented through the `ActOn` trait.
pub trait Action<T, U> {
    /// Does something.
    fn action(&mut self, val: T) -> U;
}

impl<T, U: ActOn<T, V>, V> Action<U, V> for T {
    #[inline(always)]
    fn action(&mut self, val: U) -> V {
        val.act_on(self)
    }
}

<|endoftext|>


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

//! Library for retrieving and interacting with the [crates.io index].
//!
//! [crates.io index]: https://github.com/rust-lang/crates.io-index
//!
//! ## Examples
//!
//! ```rust
//! extern crate crates_index;
//!
//! let index = crates_index::Index::new("_index".into());
//! if !index.exists() {
//!    index.retrieve().expect("Could not fetch crates.io index");
//! }
//! for crate_ in index.crates() {
//!    let latest_version = crate_.latest_version();
//!    println!("crate name: {}", latest_version.name());
//!    println!("crate version: {}", latest_version.version());
//! }
//! ```

use std::ascii::AsciiExt;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs;
use std::io::{BufRead, BufReader};
use std::path::{Path, PathBuf};

extern crate git2;
extern crate glob;
extern crate rustc_serialize;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

/// A single version of a crate published to the index
#[derive(RustcDecodable, Clone)]
pub struct Version {
    name: String,
    vers: String,
    deps: Vec<Dependency>,
    cksum: String,
    features: HashMap<String, Vec<String>>,
    yanked: bool,
}

impl Version {
    /// Name of the crate
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Name of this version
    pub fn version(&self) -> &str {
        &self.vers
    }

    /// Dependencies for this version
    pub fn dependencies(&self) -> &[Dependency] {
        &self.deps
    }

    /// Checksum of the package for this version
    pub fn checksum(&self) -> &str {
        &self.cksum
    }

    pub fn features(&self) -> &HashMap<String, Vec<String>> {
        &self.features
    }

    /// Whether this version was [yanked](http://doc.crates.io/crates-io.html#cargo-yank) from the
    /// index
    pub fn is_yanked(&self) -> bool {
        self.yanked
    }
}

/// A single dependency of a specific crate version
#[derive(RustcDecodable, Clone)]
pub struct Dependency {
    name: String,
    req: String,
    features: Vec<String>,
    optional: bool,
    default_features: bool,
    target: Option<String>,
    kind: Option<String>,
}

impl Dependency {
    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn requirement(&self) -> &str {
        &self.req
    }

    pub fn features(&self) -> &[String] {
        &self.features
    }

    pub fn is_optional(&self) -> bool {
        self.optional
    }

    pub fn has_default_features(&self) -> bool {
        self.default_features
    }

    pub fn target(&self) -> Option<&str> {
        match self.target {
            Some(ref s) => Some(s),
            None => None,
        }
    }

    pub fn kind(&self) -> Option<&str> {
        match self.kind {
            Some(ref s) => Some(s),
            None => None,
        }
    }
}

/// Constructed from `Index::crates`
pub struct Crates(CrateIndexPaths);

impl Iterator for Crates {
    type Item = Crate;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|p| Crate::new(&p))
    }
}

/// Constructed from `Index::crate_index_paths`
pub struct CrateIndexPaths(std::iter::Chain<glob::Paths, glob::Paths>);

impl CrateIndexPaths {
    fn new<P: AsRef<Path>>(path: P) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;
        let path = path.as_ref();

        let glob_pattern = format!("{}/*/*/*", path.to_str().unwrap());
        let index_paths1 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        let glob_pattern = format!("{}/[12]/*", path.to_str().unwrap());
        let index_paths2 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        CrateIndexPaths(index_paths1.chain(index_paths2))
    }
}

impl Iterator for CrateIndexPaths {
    type Item = PathBuf;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|glob_result| glob_result.unwrap())
    }
}

/// Wrapper around managing the crates.io-index git repository
pub struct Index {
    path: PathBuf,
}

impl Index {
    /// Construct a new Index supplying a path where the index lives or should live
    pub fn new(path: PathBuf) -> Index {
        Index { path: path }
    }

    /// Determines if a crates.io repository exists at `self.path`
    pub fn exists(&self) -> bool {
        git2::Repository::discover(&self.path)
            .map(|repository| {
                repository
                    .find_remote("origin")
                    .map(|remote| remote.url() == Some(INDEX_GIT_URL))
                    .unwrap_or(false)
            })
            .unwrap_or(false)
    }

    /// Downloads the index to the path specified from the constructor
    pub fn retrieve(&self) -> Result<(), git2::Error> {
        let _ = try!(git2::Repository::clone(INDEX_GIT_URL, &self.path));
        Ok(())
    }

    /// Retrieve a single crate by name (case insensitive) from the index
    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| {
                      path.file_name()
                          .and_then(OsStr::to_str)
                          .map(|file_name| file_name.eq_ignore_ascii_case(crate_name))
                          .unwrap_or(false)
                  })
            .map(|p| Crate::new(&p))
    }

    /// Retrieve an iterator over all the crates in the index
    pub fn crates(&self) -> Crates {
        Crates(self.crate_index_paths())
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> CrateIndexPaths {
        CrateIndexPaths::new(self.path.clone()) // TODO: remove this clone
    }
}

/// A single crate that contains many published versions
pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn new<P: AsRef<Path>>(index_path: P) -> Crate {
        let index_path = index_path.as_ref();
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = rustc_serialize::json::decode(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate { versions: versions }
    }

    /// Published versions of this crate sorted chronologically by date published
    pub fn versions(&self) -> &[Version] {
        &self.versions
    }

    pub fn earliest_version(&self) -> &Version {
        &self.versions[0]
    }

    pub fn latest_version(&self) -> &Version {
        &self.versions[self.versions.len() - 1]
    }
}

#[cfg(test)]
mod test {
    use std::fs;
    use super::Index;

    static TEST_INDEX_DIR: &'static str = "_test";

    #[test]
    fn test_dependencies() {
        let _ = fs::remove_dir_all(TEST_INDEX_DIR);

        let index = Index::new(TEST_INDEX_DIR.into());
        if !index.exists() {
            index.retrieve().unwrap();
        }
        let crate_ = index.crates().nth(0).unwrap();
        let version = crate_.latest_version();
        let _ = version.deps;

        let _ = fs::remove_dir_all(TEST_INDEX_DIR);
    }

    #[test]
    fn test_exists() {
        let _ = fs::remove_dir_all(TEST_INDEX_DIR);

        let index = Index::new(TEST_INDEX_DIR.into());
        assert!(!index.exists());
        index.retrieve().unwrap();
        assert!(index.exists());

        let _ = fs::remove_dir_all(TEST_INDEX_DIR);
    }
}
<commit_msg>Remove unnecessary check.<commit_after>// Copyright 2015 Corey Farwell
// Copyright 2015 Contributors of github.com/huonw/crates.io-graph
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Library for retrieving and interacting with the [crates.io index].
//!
//! [crates.io index]: https://github.com/rust-lang/crates.io-index
//!
//! ## Examples
//!
//! ```rust
//! extern crate crates_index;
//!
//! let index = crates_index::Index::new("_index".into());
//! if !index.exists() {
//!    index.retrieve().expect("Could not fetch crates.io index");
//! }
//! for crate_ in index.crates() {
//!    let latest_version = crate_.latest_version();
//!    println!("crate name: {}", latest_version.name());
//!    println!("crate version: {}", latest_version.version());
//! }
//! ```

use std::ascii::AsciiExt;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs;
use std::io::{BufRead, BufReader};
use std::path::{Path, PathBuf};

extern crate git2;
extern crate glob;
extern crate rustc_serialize;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

/// A single version of a crate published to the index
#[derive(RustcDecodable, Clone)]
pub struct Version {
    name: String,
    vers: String,
    deps: Vec<Dependency>,
    cksum: String,
    features: HashMap<String, Vec<String>>,
    yanked: bool,
}

impl Version {
    /// Name of the crate
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Name of this version
    pub fn version(&self) -> &str {
        &self.vers
    }

    /// Dependencies for this version
    pub fn dependencies(&self) -> &[Dependency] {
        &self.deps
    }

    /// Checksum of the package for this version
    pub fn checksum(&self) -> &str {
        &self.cksum
    }

    pub fn features(&self) -> &HashMap<String, Vec<String>> {
        &self.features
    }

    /// Whether this version was [yanked](http://doc.crates.io/crates-io.html#cargo-yank) from the
    /// index
    pub fn is_yanked(&self) -> bool {
        self.yanked
    }
}

/// A single dependency of a specific crate version
#[derive(RustcDecodable, Clone)]
pub struct Dependency {
    name: String,
    req: String,
    features: Vec<String>,
    optional: bool,
    default_features: bool,
    target: Option<String>,
    kind: Option<String>,
}

impl Dependency {
    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn requirement(&self) -> &str {
        &self.req
    }

    pub fn features(&self) -> &[String] {
        &self.features
    }

    pub fn is_optional(&self) -> bool {
        self.optional
    }

    pub fn has_default_features(&self) -> bool {
        self.default_features
    }

    pub fn target(&self) -> Option<&str> {
        match self.target {
            Some(ref s) => Some(s),
            None => None,
        }
    }

    pub fn kind(&self) -> Option<&str> {
        match self.kind {
            Some(ref s) => Some(s),
            None => None,
        }
    }
}

/// Constructed from `Index::crates`
pub struct Crates(CrateIndexPaths);

impl Iterator for Crates {
    type Item = Crate;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|p| Crate::new(&p))
    }
}

/// Constructed from `Index::crate_index_paths`
pub struct CrateIndexPaths(std::iter::Chain<glob::Paths, glob::Paths>);

impl CrateIndexPaths {
    fn new<P: AsRef<Path>>(path: P) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;
        let path = path.as_ref();

        let glob_pattern = format!("{}/*/*/*", path.to_str().unwrap());
        let index_paths1 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        let glob_pattern = format!("{}/[12]/*", path.to_str().unwrap());
        let index_paths2 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        CrateIndexPaths(index_paths1.chain(index_paths2))
    }
}

impl Iterator for CrateIndexPaths {
    type Item = PathBuf;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|glob_result| glob_result.unwrap())
    }
}

/// Wrapper around managing the crates.io-index git repository
pub struct Index {
    path: PathBuf,
}

impl Index {
    /// Construct a new Index supplying a path where the index lives or should live
    pub fn new(path: PathBuf) -> Index {
        Index { path: path }
    }

    /// Determines if a crates.io repository exists at `self.path`
    pub fn exists(&self) -> bool {
        git2::Repository::discover(&self.path)
            .map(|repository| {
                repository
                    .find_remote("origin")
                    .map(|remote| remote.url() == Some(INDEX_GIT_URL))
                    .unwrap_or(false)
            })
            .unwrap_or(false)
    }

    /// Downloads the index to the path specified from the constructor
    pub fn retrieve(&self) -> Result<(), git2::Error> {
        let _ = try!(git2::Repository::clone(INDEX_GIT_URL, &self.path));
        Ok(())
    }

    /// Retrieve a single crate by name (case insensitive) from the index
    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| {
                      path.file_name()
                          .and_then(OsStr::to_str)
                          .map(|file_name| file_name.eq_ignore_ascii_case(crate_name))
                          .unwrap_or(false)
                  })
            .map(|p| Crate::new(&p))
    }

    /// Retrieve an iterator over all the crates in the index
    pub fn crates(&self) -> Crates {
        Crates(self.crate_index_paths())
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> CrateIndexPaths {
        CrateIndexPaths::new(self.path.clone()) // TODO: remove this clone
    }
}

/// A single crate that contains many published versions
pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn new<P: AsRef<Path>>(index_path: P) -> Crate {
        let index_path = index_path.as_ref();
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = rustc_serialize::json::decode(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate { versions: versions }
    }

    /// Published versions of this crate sorted chronologically by date published
    pub fn versions(&self) -> &[Version] {
        &self.versions
    }

    pub fn earliest_version(&self) -> &Version {
        &self.versions[0]
    }

    pub fn latest_version(&self) -> &Version {
        &self.versions[self.versions.len() - 1]
    }
}

#[cfg(test)]
mod test {
    use std::fs;
    use super::Index;

    static TEST_INDEX_DIR: &'static str = "_test";

    #[test]
    fn test_dependencies() {
        let _ = fs::remove_dir_all(TEST_INDEX_DIR);

        let index = Index::new(TEST_INDEX_DIR.into());
        let crate_ = index.crates().nth(0).unwrap();
        let version = crate_.latest_version();
        let _ = version.deps;

        let _ = fs::remove_dir_all(TEST_INDEX_DIR);
    }

    #[test]
    fn test_exists() {
        let _ = fs::remove_dir_all(TEST_INDEX_DIR);

        let index = Index::new(TEST_INDEX_DIR.into());
        assert!(!index.exists());
        index.retrieve().unwrap();
        assert!(index.exists());

        let _ = fs::remove_dir_all(TEST_INDEX_DIR);
    }
}
<|endoftext|>


<commit_before>#![feature(custom_derive)]
#![feature(proc_macro)]

#[macro_use]
extern crate log;

#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;

extern crate slog_stdlog;
extern crate slog_envlogger;

use serde_json::Value;
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::slice::Iter;

#[derive(Deserialize, Debug)]
pub struct Response {
    took: u64,
    timed_out: bool,
    _shards: Shards,
    hits: Hits,
    aggregations: Option<Aggregations>,
    status: Option<u16>
}

#[derive(Deserialize, Debug)]
pub struct Aggregations(Value);

//QUESTION: Why do lifetimes go where they go, what am I missing?
//          What happens when lifetimes shadow each other?
//          Mental model for this?
//          Below works thanks to `misdreavus` on IRC, but I don't quite know why
impl<'a> IntoIterator for &'a Aggregations {
    type Item = RowData<'a>; // JPG - str?
    type IntoIter = AggregationIterator<'a>;

    fn into_iter(self) -> AggregationIterator<'a> {
        AggregationIterator::new(self)
    }
}

// struct Foo<'a>(&'a String);

// fn foo() {
//     let a = String::from("a"); // a
//     let b = String::from("b"); // |  b
//                                // |  |
//     Foo(&b);                   // |  |
//                                // |  |
//     let c = a;                 //    |  c
//                                //    |  |
// }

//FIXME: can this be run as a state-machine (ala https://hoverbear.org/2016/10/12/rust-state-machine-pattern/)
//#[derive(Debug)]
//enum AggStates {
//    AtRoot,
//    AtName,
//    InBuckets,
//    AtValues,
//    RowFinished
//}

// Why we might want multiple lifetimes.
// #[derive(Copy)]
// struct Cache<'c, 's> {
//     thing: &'c BTreeMap<usize, &'s str>,
//     position: usize,
// }

// fn foo<'c, 's>(cache: Cache<'c, 's>) -> &'s str {
//     unimplemented!()
// }

// fn main() {
//     let many_strings = "foo";                           // 0 |
//     let z = {                                           // 1 |
//         let map = BTreeMap! { 0 => many_strings };      // 2 | |
//         let cache = Cache { thing: &map, position: 0 }; // 3 | |
//         foo(cache);                                     // 4 | |
//     };                                                  // 5 |
//     println!("{}", z);                                  // 6 |
// }

#[derive(Debug)]
pub struct AggregationIterator<'a> {
    current_row: Option<RowData<'a>>,
    current_row_finished: bool,
    //QUESTION: Tracking traversal usng a stack of Iterators make sense? Is Vec right for this?
    iter_stack: Vec<(Option<&'a String>, Iter<'a, Value>)>,
    aggregations: &'a Aggregations
}

impl<'a> AggregationIterator<'a> {
    fn new(a: &'a Aggregations) -> AggregationIterator<'a> {
        let o = a.0.as_object()
            .expect("Not implemented, we only cater for bucket objects");
        //FIXME: Bad for lib // JPG: quick-error

        let s = o.into_iter().filter_map(|(key, child)| {
            child.as_object()
                .and_then(|child| child.get("buckets"))
                .and_then(Value::as_array)
                .map(|array| (Some(key), array.iter()))
        }).collect();

        AggregationIterator {
            current_row: None,
            current_row_finished: false,
            iter_stack: s,
            aggregations: a
        }
    }
}

type Object = BTreeMap<String, Value>;
type RowData<'a> = BTreeMap<Cow<'a, str>, &'a Value>;

fn insert_value<'a>(fieldname: &str, json_object: &'a Object, keyname: &str, rowdata: &mut RowData<'a>) {
    if let Some(v) = json_object.get(fieldname) {
        let field_name = format!("{}_{}", keyname, fieldname);
        debug! ("ITER: Insert value! {} {:?}", field_name, v);
        rowdata.insert(Cow::Owned(field_name), v);
    }
}

impl<'a> Iterator for AggregationIterator<'a> {
    type Item = RowData<'a>; // JPG type alias?

    fn next(&mut self) -> Option<RowData<'a>> {
        if self.current_row.is_none() {
            //New row
            self.current_row = Some(BTreeMap::new())
        }

        loop {
            match self.iter_stack.pop() {
                None => {
                    debug! ("ITER: Done!"); // JPG: no space on macro invocation
                    self.current_row = None;
                    break;
                },
                Some(mut i) => {
                    let n = i.1.next(); // JPG tuples used like this are hard to follow
                    //FIXME: can this fail?
                    let active_name = &i.0.unwrap();

                    //Iterate down?
                    let mut has_buckets = false;
                    //Save
                    self.iter_stack.push(i);

                    debug! ("ITER: Depth {}", self.iter_stack.len());
                    //FIXME: Move this, to be able to process first line too
                    match n {
                        None => {
                            //Was nothing here, exit
                            debug! ("ITER: Exit!");
                            self.iter_stack.pop();
                            continue;
                        },
                        Some(n) => {
                            //QUESTION: Destructuring/matching to this extent the right strategy?
                            match self.current_row {
                                Some(ref mut row) => {
                                    debug! ("ITER: Row: {:?}", row);

                                    let o = n.as_object().expect("Shouldn't get here!");
                                    for (key, value) in o {
                                        match *value {
                                            Value::Object(ref c) => {
                                                //Child Aggregation
                                                if let Some(buckets) = c.get("buckets") {
                                                    has_buckets = true;
                                                    if let Value::Array(ref a) = *buckets {
                                                        let i = a.iter();
                                                        self.iter_stack.push((Some(key), i));
                                                    }
                                                    continue;
                                                }
                                                //Simple Value Aggregation Name
                                                if let Some(v) = c.get("value") {
                                                    debug! ("ITER: Insert value! {} {:?}", key, v);
                                                    //QUESTION: Cow right for this use-case? See below
                                                    row.insert(Cow::Borrowed(key), v);
                                                    continue;
                                                }
                                                //Stats
                                                //FIXME: Can be done in loop?

                                                //Stats fields
                                                insert_value("count",c,key,row);
                                                insert_value("min",c,key,row);
                                                insert_value("max",c,key,row);
                                                insert_value("avg",c,key,row);
                                                insert_value("sum",c,key,row);
                                                insert_value("sum_of_squares",c,key,row);
                                                insert_value("variance",c,key,row);
                                                insert_value("std_deviation",c,key,row);

                                                //TODO: std_deviation_bounds
//                                                if c.contains_key("std_deviation_bounds") {
//                                                    let u = c.get("std_deviation_bounds").unwrap().get("upper");
//                                                    let l = c.get("std_deviation_bounds").unwrap().get("lower");
//                                                    let un = format!("{}_std_deviation_bounds_upper", key);
//                                                    let ln = format!("{}_std_deviation_bounds_lower", key);
//                                                    debug! ("ITER: Insert std_dev_bounds! {} {} u: {:?} l: {:?}", un, ln, u.unwrap(), l.unwrap());
//                                                    row.insert(Cow::Owned(un), u.unwrap());
//                                                    row.insert(Cow::Owned(ln), l.unwrap());
//                                                }
                                            },
                                            _ => ()
                                        }
                                        //Bucket Aggregation Name
                                        if key == "key" {
                                            debug! ("ITER: Insert bucket! {} {:?}", active_name, value);
                                            row.insert(Cow::Borrowed(active_name), value);
                                        }
                                        //Bucket Aggregation Count
                                        if key == "doc_count" {
                                            debug! ("ITER: Insert bucket count! {} {:?}", active_name, value);
                                            let field_name = format!("{}_doc_count", active_name);
                                            row.insert(Cow::Owned(field_name), value);
                                        }
                                    }
                                    //Return here?
                                    if !has_buckets {
                                        return Some(row.clone());
                                    }
                                },
                                _ => ()
                            }
                        }
                    }

                    if !has_buckets {
                        debug! ("ITER: Bucketless!");
                        break;
                    } else {
                        debug! ("ITER: Dive!");
                    }
                }
            };
        }

        match self.current_row {
            //FIXME: Refactor to avoid this clone()
            Some(ref x) => Some(x.clone()),
            None => None
        }
    }
}

#[derive(Deserialize, Debug)]
struct Shards {
    total: u32,
    successful: u32,
    failed: u32
}

#[derive(Deserialize, Debug)]
pub struct Hits {
    total: u64,
    max_score: u64,
    hits: Vec<Value>
}

// JPG place impls closer to defns
impl Response {
    pub fn hits(&self) -> &Vec<Value> {
        &self.hits.hits()
    }

    pub fn aggs(&self) -> Option<&Aggregations> {
        self.aggregations.as_ref()
    }
}

impl Hits {
    pub fn hits(&self) -> &Vec<Value> { // JPG http://stackoverflow.com/q/40006219/155423
        &self.hits
    }
}

#[derive(Deserialize, Debug)]
struct Hit {
    _index: String // JPG suspicious
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {}
}
<commit_msg>WIP: Merge shepmaster changes<commit_after>#![feature(custom_derive)]
#![feature(proc_macro)]

#[macro_use]
extern crate log;

#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;

extern crate slog_stdlog;
extern crate slog_envlogger;

use serde_json::Value;
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::slice::Iter;

impl Response {
    pub fn hits(&self) -> &Vec<Value> {
        &self.hits.hits()
    }

    pub fn aggs(&self) -> Option<&Aggregations> {
        self.aggregations.as_ref()
    }
}

#[derive(Deserialize, Debug)]
pub struct Response {
    took: u64,
    timed_out: bool,
    _shards: Shards,
    hits: Hits,
    aggregations: Option<Aggregations>,
    status: Option<u16>
}

#[derive(Deserialize, Debug)]
pub struct Aggregations(Value);

impl<'a> IntoIterator for &'a Aggregations {
    type Item = RowData<'a>;
    type IntoIter = AggregationIterator<'a>;

    fn into_iter(self) -> AggregationIterator<'a> {
        AggregationIterator::new(self)
    }
}

//FIXME: can this be run as a state-machine (ala https://hoverbear.org/2016/10/12/rust-state-machine-pattern/)
//#[derive(Debug)]
//enum AggStates {
//    AtRoot,
//    AtName,
//    InBuckets,
//    AtValues,
//    RowFinished
//}

#[derive(Debug)]
pub struct AggregationIterator<'a> {
    current_row: Option<RowData<'a>>,
    current_row_finished: bool,
    iter_stack: Vec<(Option<&'a String>, Iter<'a, Value>)>,
    aggregations: &'a Aggregations
}

impl<'a> AggregationIterator<'a> {
    fn new(a: &'a Aggregations) -> AggregationIterator<'a> {
        let o = a.0.as_object()
            .expect("Not implemented, we only cater for bucket objects");
        //FIXME: Bad for lib // JPG: quick-error

        let s = o.into_iter().filter_map(|(key, child)| {
            child.as_object()
                .and_then(|child| child.get("buckets"))
                .and_then(Value::as_array)
                .map(|array| (Some(key), array.iter()))
        }).collect();

        AggregationIterator {
            current_row: None,
            current_row_finished: false,
            iter_stack: s,
            aggregations: a
        }
    }
}

type Object = BTreeMap<String, Value>;
type RowData<'a> = BTreeMap<Cow<'a, str>, &'a Value>;

fn insert_value<'a>(fieldname: &str, json_object: &'a Object, keyname: &str, rowdata: &mut RowData<'a>) {
    if let Some(v) = json_object.get(fieldname) {
        let field_name = format!("{}_{}", keyname, fieldname);
        debug! ("ITER: Insert value! {} {:?}", field_name, v);
        rowdata.insert(Cow::Owned(field_name), v);
    }
}

impl<'a> Iterator for AggregationIterator<'a> {
    type Item = RowData<'a>;

    fn next(&mut self) -> Option<RowData<'a>> {
        if self.current_row.is_none() {
            //New row
            self.current_row = Some(BTreeMap::new())
        }

        loop {
            match self.iter_stack.pop() {
                None => {
                    debug! ("ITER: Done!");
                    self.current_row = None;
                    break;
                },
                Some(mut i) => {
                    let n = i.1.next();
                    //FIXME: can this fail?
                    let active_name = &i.0.unwrap();

                    //Iterate down?
                    let mut has_buckets = false;
                    //Save
                    self.iter_stack.push(i);

                    debug! ("ITER: Depth {}", self.iter_stack.len());
                    //FIXME: Move this, to be able to process first line too
                    match n {
                        None => {
                            //Was nothing here, exit
                            debug! ("ITER: Exit!");
                            self.iter_stack.pop();
                            continue;
                        },
                        Some(n) => {
                            match self.current_row {
                                Some(ref mut row) => {
                                    debug! ("ITER: Row: {:?}", row);

                                    let o = n.as_object().expect("Shouldn't get here!");
                                    for (key, value) in o {
                                        match *value {
                                            Value::Object(ref c) => {
                                                //Child Aggregation
                                                if let Some(buckets) = c.get("buckets") {
                                                    has_buckets = true;
                                                    if let Value::Array(ref a) = *buckets {
                                                        let i = a.iter();
                                                        self.iter_stack.push((Some(key), i));
                                                    }
                                                    continue;
                                                }
                                                //Simple Value Aggregation Name
                                                if let Some(v) = c.get("value") {
                                                    debug! ("ITER: Insert value! {} {:?}", key, v);
                                                    //QUESTION: Cow right for this use-case? See below
                                                    row.insert(Cow::Borrowed(key), v);
                                                    continue;
                                                }
                                                //Stats
                                                //FIXME: Can be done in loop?

                                                //Stats fields
                                                insert_value("count",c,key,row);
                                                insert_value("min",c,key,row);
                                                insert_value("max",c,key,row);
                                                insert_value("avg",c,key,row);
                                                insert_value("sum",c,key,row);
                                                insert_value("sum_of_squares",c,key,row);
                                                insert_value("variance",c,key,row);
                                                insert_value("std_deviation",c,key,row);

                                                //TODO: std_deviation_bounds
//                                                if c.contains_key("std_deviation_bounds") {
//                                                    let u = c.get("std_deviation_bounds").unwrap().get("upper");
//                                                    let l = c.get("std_deviation_bounds").unwrap().get("lower");
//                                                    let un = format!("{}_std_deviation_bounds_upper", key);
//                                                    let ln = format!("{}_std_deviation_bounds_lower", key);
//                                                    debug! ("ITER: Insert std_dev_bounds! {} {} u: {:?} l: {:?}", un, ln, u.unwrap(), l.unwrap());
//                                                    row.insert(Cow::Owned(un), u.unwrap());
//                                                    row.insert(Cow::Owned(ln), l.unwrap());
//                                                }
                                            },
                                            _ => ()
                                        }
                                        //Bucket Aggregation Name
                                        if key == "key" {
                                            debug! ("ITER: Insert bucket! {} {:?}", active_name, value);
                                            row.insert(Cow::Borrowed(active_name), value);
                                        }
                                        //Bucket Aggregation Count
                                        if key == "doc_count" {
                                            debug! ("ITER: Insert bucket count! {} {:?}", active_name, value);
                                            let field_name = format!("{}_doc_count", active_name);
                                            row.insert(Cow::Owned(field_name), value);
                                        }
                                    }
                                    //Return here?
                                    if !has_buckets {
                                        return Some(row.clone());
                                    }
                                },
                                _ => ()
                            }
                        }
                    }

                    if !has_buckets {
                        debug! ("ITER: Bucketless!");
                        break;
                    } else {
                        debug! ("ITER: Dive!");
                    }
                }
            };
        }

        match self.current_row {
            //FIXME: Refactor to avoid this clone()
            Some(ref x) => Some(x.clone()),
            None => None
        }
    }
}

#[derive(Deserialize, Debug)]
struct Shards {
    total: u32,
    successful: u32,
    failed: u32
}

#[derive(Deserialize, Debug)]
pub struct Hits {
    total: u64,
    max_score: u64,
    hits: Vec<Value>
}

impl Hits {
    pub fn hits(&self) -> &Vec<Value> { // JPG http://stackoverflow.com/q/40006219/155423
        &self.hits
    }
}

#[derive(Deserialize, Debug)]
struct Hit {
    _index: String
}
<|endoftext|>


<commit_before>#[test]
fn it_works() {
}
<commit_msg>feat: add merges stuff; first working version<commit_after>#![feature(phase)]
#[phase(plugin)]
extern crate regex_macros;
extern crate regex;
extern crate serialize;
extern crate collections;

use regex::Regex;
use serialize::Decodable;
use collections::treemap::TreeMap;
use serialize::json;
use serialize::json::{Json, JsonObject, JsonList};
use serialize::json::ToJson;
use std::from_str::FromStr;

static parent_regexp: Regex = regex!(r"^([^][]+)");
static child_regexp: Regex = regex!(r"(\[[^][]*\])");

trait MutableJson {
	fn as_object_mut<'a>(&'a mut self) -> Option<&'a mut JsonObject>;
	fn as_list_mut<'a>(&'a mut self) -> Option<&'a mut JsonList>;
}

impl MutableJson for Json {

    /// If the Json value is an Object, returns the associated TreeMap.
    /// Returns None otherwise.
    fn as_object_mut<'a>(&'a mut self) -> Option<&'a mut JsonObject> {
        match self {
            &json::Object(ref mut map) => Some(&mut*map),
            _ => None
        }
    }

    fn as_list_mut<'a>(&'a mut self) -> Option<&'a mut JsonList> {
        match self {
            &json::List(ref mut list) => Some(&mut *list),
            _ => None
        }
    }

}

fn parse_pairs(body: &str) -> Vec<(&str, Option<&str>)> {

	let mut pairs = vec![];

	for part in body.split_str("&") {
		let separator = part.find_str("]=")
							.and_then(|pos| Some(pos+1))
							.or_else(|| part.find_str("="));

		match separator {
			None => pairs.push((part, None)),
			Some(pos) => {
				let key = part.slice_to(pos);
				let val = part.slice_from(pos + 1);
				pairs.push((key, Some(val)));
			}
		}
	}

	return pairs
}

fn parse_key(key: &str) -> Vec<&str> {
	let mut keys = vec![];

	match parent_regexp.captures(key) {
		Some(captures) => keys.push(captures.at(1)),
		None => ()
	};

	for captures in child_regexp.captures_iter(key) {
		keys.push(captures.at(1));
	}

	keys
}

fn cleanup_key(key: &str) -> &str {
	if key.starts_with("[") && key.ends_with("]") {
		key.slice_chars(1, key.len()-1)
	} else {
		key
	}
}

fn index(obj: &JsonObject) -> Option<uint> {
	let mut index = 0;
	let mut has_index = false;
	for key in obj.keys() {
		let num_key: Option<uint> = from_str(key.as_slice());
		match num_key {
			Some(idx) if index <= idx => {
				index = idx;
				has_index = true;
			},
			_ => ()
		}
	}

	if (has_index) {
		Some(index)
	} else {
		None
	}
}

fn next_index(obj: &JsonObject) -> uint {
	match index(obj) {
		Some(idx) => idx + 1,
		None => 0
	}
}

fn object_from_list(obj: &Json) -> Json {
	let list = obj.as_list().unwrap();
	let mut tree: TreeMap<String,Json> = TreeMap::new();

	for (idx, item) in list.iter().enumerate() {
		tree.insert(idx.to_string(), item.clone());
	}

	tree.to_json()
}

fn create_array() -> Json {
	let vec: Vec<Json> = vec![];
	return json::List(vec);
}

fn push_item_to_array(array: &mut Json, item: Json) {
	let vec = array.as_list_mut().unwrap();
	vec.push(item);
}

fn create_idx_merger(idx: uint, obj: Json) -> Json {
	let mut tree: TreeMap<String,Json> = TreeMap::new();
	tree.insert("__idx".to_string(), idx.to_json());
	tree.insert("__object".to_string(), obj);
	return json::Object(tree)
}

fn create_object_with_key(key: String, obj: Json) -> Json {
	let mut tree: TreeMap<String,Json> = TreeMap::new();
	tree.insert(key, obj);
	return json::Object(tree)
}

fn apply_object(keys: &[&str], val: Json) -> Json {

	if (keys.len() > 0) {
		let key = *keys.get(0).unwrap();
		if key == "[]" {
			let mut new_array = create_array();
			let item = apply_object(keys.tail(), val);
			push_item_to_array(&mut new_array, item);
			return new_array;
		} else {
			let key = cleanup_key(key);
			let array_index: Option<uint> = from_str(key);

			match array_index {
				Some(idx) => {
					let result = apply_object(keys.tail(), val);
					let item = create_idx_merger(idx, result);
					return item;
				},
				None => {
					return create_object_with_key(key.to_string(), apply_object(keys.tail(), val));
				}
			}
		}

	} else {
		return val;
	}
}

fn merge_object_and_array(to: &mut Json, from: &Json) -> Option<Json> {
	let tree = to.as_object_mut().unwrap();
	let vec = from.as_list().unwrap();
	let index = next_index(tree);

	for (idx, item) in vec.iter().enumerate() {
		tree.insert((index + idx).to_string(), item.clone());
	}

	None
}

fn merge_object_and_merger(to: &mut Json, from: &Json) -> Option<Json> {

	let to_tree = to.as_object_mut().unwrap();
	let from_tree = from.as_object().unwrap();

	let to_index = from_tree.find(&"__idx".to_string()).unwrap().as_u64().unwrap().to_string();
	let source_obj = from_tree.find(&"__object".to_string()).unwrap();
	let has_dest_obj = {
		match to_tree.find(&to_index) {
			Some(&json::Object(_)) => true,
			Some(&json::List(_)) => true,
			Some(_) => false,
			None => false
		}
	};

	if has_dest_obj {
		let merge_result = merge(to_tree.find_mut(&to_index).unwrap(), source_obj);
		match merge_result {
			Some(result) => { to_tree.insert(to_index, result); },
			None => ()
		}
	} else {
		to_tree.insert(to_index, source_obj.clone());
	}

	None
}

fn merge_object_and_object(to: &mut Json, from: &Json) -> Option<Json> {
	let to_tree = to.as_object_mut().unwrap();
	let from_tree = from.as_object().unwrap();

	for (key, value) in from_tree.iter() {
		let has_dest_obj = {
			match to_tree.find(key) {
				Some(&json::Object(_)) => true,
				Some(&json::List(_)) => true,
				Some(_) => false,
				None => false
			}
		};

		if (has_dest_obj) {
			let merge_result = merge(to_tree.find_mut(key).unwrap(), value);
			match merge_result {
				Some(result) => { to_tree.insert(key.to_string(), result); },
				None => ()
			}
		} else {
			to_tree.insert(key.to_string(), value.clone());
		}

	}

	None
}

fn merge_list_and_list(to: &mut Json, from: &Json) -> Option<Json> {
	let to_vec = to.as_list_mut().unwrap();
	let from_vec = from.as_list().unwrap();

	for value in from_vec.iter() {
		to_vec.push(value.clone());
	}

	None
}

fn merge_list_and_merger(to: &mut Json, from: &Json) -> Option<Json> {

	let to_vec = to.as_list_mut().unwrap();

	let from_tree = from.as_object().unwrap();
	let to_index = from_tree.find(&"__idx".to_string()).unwrap().as_u64().unwrap() as uint;
	let source_obj = from_tree.find(&"__object".to_string()).unwrap();

	if (to_index < to_vec.len()) {
		// merge existing item
		let merge_result = merge(to_vec.get_mut(to_index), source_obj);
		match merge_result {
			Some(result) => {
				to_vec.remove(to_index);
				println!("Insert {}", result);
				to_vec.insert(to_index, result);
			},
			None => ()
		}
		None
	} else if (to_index == to_vec.len()) {
		to_vec.insert(to_index, source_obj.clone());
		None
	} else {
		let mut new_obj = object_from_list(&to_vec.to_json());
		merge_object_and_merger(&mut new_obj, from);
		return Some(new_obj);
	}
}

fn is_merger(obj: &Json) -> bool {
	let tree = obj.as_object().unwrap();
	let idx = tree.find(&"__idx".to_string());
	match idx {
		Some(idx) => idx.is_number(),
		None => false
	}
}

fn merge_list_and_object(to: &mut Json, from: &Json) -> Option<Json> {
	let mut to_tree = object_from_list(to);

	merge(&mut to_tree, from);
	Some(to_tree)
}

fn merge(target: &mut Json, source: &Json) -> Option<Json> {

	println!("Merge {} with {}", target.to_pretty_str(), source.to_pretty_str());

	match target {
		&json::Object(_) => {
			match source {
				&json::List(_) => merge_object_and_array(target, source),
				&json::Object(_) if is_merger(source) => merge_object_and_merger(target, source),
				&json::Object(_) => merge_object_and_object(target, source),
				&json::String(_) => return Some(source.clone()),
				_ => fail!("Unknown merge")
			}
		}
		&json::List(_) => {
			match source {
				&json::List(_) => merge_list_and_list(target, source),
				&json::Object(_) if is_merger(source) => merge_list_and_merger(target, source),
				&json::Object(_) => merge_list_and_object(target, source),
				&json::String(_) => return Some(source.clone()),
				_ => fail!("Unknown merge")
			}
		},
		&json::String(_) => {
			return Some(source.clone())
		}
		_ => fail!("Unknown merge")
	}

}

fn parse(params: &str) -> Json {
	let mut tree: TreeMap<String,Json> = TreeMap::new();
	let mut obj = tree.to_json();
	let pairs = parse_pairs(params);
	for &(key, value) in pairs.iter() {
		let partial = apply_object(parse_key(key).slice_from(0), value.unwrap_or("").to_string().to_json());
		println!("PARTIAL {}", partial.to_pretty_str());
		merge(&mut obj, &partial);
	}

	obj
}

#[test]
fn it_parse_pairs() {
	assert_eq!(vec![("key", Some("val")), ("val[][][]", Some("1"))], parse_pairs("key=val&val[][][]=1"))
}

#[test]
fn it_parse_keys() {
	assert_eq!(parse_key("0"), vec!["0"]);
	assert_eq!(parse_key("foo"), vec!["foo"]);
	assert_eq!(parse_key("a[]"), vec!["a", "[]"]);
	assert_eq!(parse_key("a[>=]"), vec!["a", "[>=]"]);
	assert_eq!(parse_key("a[<=>]"), vec!["a", "[<=>]"]);
	assert_eq!(parse_key("a[==]"), vec!["a", "[==]"]);
	assert_eq!(parse_key("foo"), vec!["foo"]);
	assert_eq!(parse_key(" foo "), vec![" foo "]);
    assert_eq!(parse_key("a[b]"), vec!["a", "[b]"]);
	assert_eq!(parse_key("a[b][c]"), vec!["a", "[b]", "[c]"]);
	assert_eq!(parse_key("a[b][c][d][e][f][g][h]"), vec!["a", "[b]", "[c]", "[d]", "[e]", "[f]", "[g]", "[h]"]);
	assert_eq!(parse_key("a[12b]"), vec!["a", "[12b]"]);
	assert_eq!(parse_key("he=llo"), vec!["he=llo"]);
	assert_eq!(parse_key("a[b c]"), vec!["a", "[b c]"]);
	assert_eq!(parse_key("a[2]"), vec!["a", "[2]"]);
	assert_eq!(parse_key("a[99999999]"), vec!["a", "[99999999]"]);
	assert_eq!(parse_key("{%:%}"), vec!["{%:%}"]);
	assert_eq!(parse_key("foo"), vec!["foo"]);
	assert_eq!(parse_key("_r"), vec!["_r"]);
	assert_eq!(parse_key("[foo]"), vec!["[foo]"]);
	assert_eq!(parse_key("[]"), vec!["[]"]);
}

#[test]
fn it_builds_object() {
	println!("{}", parse("key[]=1&key[0]=2").to_json().to_pretty_str())

	fail!("{}")
}<|endoftext|>


<commit_before>extern crate mio;
extern crate regex;

#[cfg(test)]
mod tests;

pub mod route;
pub mod request;
pub mod response;

use std::io::Result;
use std::io::prelude::*;
use std::net::ToSocketAddrs;
use std::collections::HashMap;
use std::collections::HashSet;
use mio::tcp::{TcpListener, TcpStream};
use mio::util::Slab;
use mio::*;

pub use route::*;
pub use request::*;
pub use response::*;

struct Client {
    sock:   TcpStream,
    token:  Token,
    events: EventSet,
    i_buf:  Vec<u8>,
    o_buf:  Vec<u8>,
}

impl Client {
    fn new(sock: TcpStream, token: Token) -> Client {
        Client {
            sock:   sock,
            token:  token,
            events: EventSet::hup(),
            i_buf:  Vec::new(),
            o_buf:  Vec::new(),
        }
    }

    fn receive(&mut self) -> Result<bool> {
        let mut buf: Vec<u8> = Vec::with_capacity(2048);

        match self.sock.try_read_buf(&mut buf) {
            Ok(size)  => {
                match size {
                    Some(_) => {
                        self.events.remove(EventSet::readable());
                        self.events.insert(EventSet::writable());
                        self.i_buf.extend(buf);
                        return Ok(true);
                    },
                    None    => {
                        return Ok(false);
                    },
                }
            },
            Err(e)  => {
                panic!("failed to read from socket! <token: {:?}> <error: {:?}>", self.token, e);
            },
        }

        Ok(false)
    }

    /* write the client's output buffer to the socket.
     *
     * the following return values mean:
     *  - Ok(true):  we can close the connection
     *  - Ok(false): keep listening for writeable event and continue next time
     *  - Err(e):    something dun fucked up
     */
    fn send(&mut self) -> Result<bool> {
        let out = self.o_buf.clone();

        match self.sock.write(&out.as_slice()) {
            Ok(sz)  => {
                if sz == self.o_buf.len() {
                    /* we did it! */
                    self.events.remove(EventSet::writable());
                    return Ok(true);
                } else {
                    self.o_buf = self.o_buf.split_off(sz);

                    return Ok(false);
                }
            },
            Err(e)  => {
                panic!("failed to write to socket! <token: {:?}> <error: {:?}>", self.token, e);
            }
        }

        Ok(false)
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        self.events.insert(EventSet::readable());

        evl.register(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.reregister(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to re-register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }
}

/* our primary object. similar interface to Flask, the
 * Python microframework. much faster, however! :)
 */
pub struct Canteen {
    routes:  HashMap<RouteDef, Route>,
    server:  TcpListener,
    token:   Token,
    conns:   Slab<Client>,
    default: fn(&Request) -> Response,
}

impl Handler for Canteen {
    type Timeout = ();
    type Message = u32;

    fn ready(&mut self, evl: &mut EventLoop<Canteen>, token: Token, events: EventSet) {
        if events.is_error() || events.is_hup() {
            self.reset_connection(token);
            return;
        }

        if events.is_readable() {
            if self.token == token {
                self.accept(evl);
            } else {
                self.readable(evl, token)
                    .and_then(|_| self.get_client(token)
                                      .reregister(evl))
                    .unwrap_or_else(|e| {
                        panic!("read event failed! <token: {:?}> <error: {:?}>", token, e);
                    });
            }

            return;
        }

        if events.is_writable() {
            match self.get_client(token).send() {
                Ok(true)    => { self.reset_connection(token); },
                Ok(false)   => { let _ = self.get_client(token).reregister(evl); },
                Err(_)      => { panic!("something really bad happened!"); },
            }
        }
    }
}

impl Canteen {
    pub fn new<A: ToSocketAddrs>(addr: A) -> Canteen {
        Canteen {
            routes:  HashMap::new(),
            server:  TcpListener::bind(&addr.to_socket_addrs().unwrap().next().unwrap()).unwrap(),
            token:   Token(1),
            conns:   Slab::new_starting_at(Token(2), 2048),
            default: Route::err_404,
        }
    }

    pub fn add_route(&mut self, path: &str, mlist: Vec<Method>, handler: fn(&Request) -> Response) -> &mut Canteen {
        let mut methods: HashSet<Method> = HashSet::new();

        for m in mlist {
            methods.insert(m);
        }

        for m in methods {
            let rd = RouteDef {
                pathdef:    String::from(path),
                method:     m,
            };

            if self.routes.contains_key(&rd) {
                panic!("a route handler for {} has already been defined!", path);
            }

            self.routes.insert(rd, Route::new(&path, m, handler));
        }

        self
    }

    pub fn set_default(&mut self, handler: fn(&Request) -> Response) {
        self.default = handler;
    }

    fn get_client<'a>(&'a mut self, token: Token) -> &'a mut Client {
        &mut self.conns[token]
    }

    fn accept(&mut self, evl: &mut EventLoop<Canteen>) {
        let (sock, _) = match self.server.accept() {
            Ok(s)   => {
                match s {
                    Some(sock)  => sock,
                    None        => {
                        panic!("failed to accept new connection!");
                    }
                }
            },
            Err(e)  => {
                panic!("failed to accept new connection! <error: {:?}>", e);
            },
        };

        match self.conns.insert_with(|token| Client::new(sock, token)) {
            Some(token) => {
                match self.get_client(token).register(evl) {
                    Ok(_)   => {},
                    Err(e)  => {
                        panic!("failed to register client! <token: {:?}> <error: {:?}>", token, e);
                    },
                }
            },
            None        => {
                panic!("failed to add client connection!");
            },
        }

        self.reregister(evl);
    }

    fn handle_request(&self, req: &mut Request) -> Vec<u8> {
        let mut handler: fn(&Request) -> Response = self.default;

        for (_, route) in &self.routes {
            match (route).is_match(req) {
                true  => {
                    handler = route.handler;
                    req.params = route.parse(&req.path);
                    break;
                },
                false => continue,
            }
        }

        handler(req).gen_output()
    }

    fn readable(&mut self, evl: &mut EventLoop<Canteen>, token: Token) -> Result<bool> {
        match self.get_client(token).receive() {
            Ok(true)    => {
                let buf = self.get_client(token).i_buf.clone();
                let rqstr = String::from_utf8(buf).unwrap();
                let mut req = Request::from_str(&rqstr);
                let output = self.handle_request(&mut req);

                self.get_client(token).o_buf.extend(output);
            },
            Ok(false)   => {},
            Err(e)      => {
                panic!("message wasn't actually readable! <error: {:?}>", e);
            },
        };

        let _ = self.get_client(token).reregister(evl);

        Ok(true)
    }

    fn reset_connection(&mut self, token: Token) {
        /* kill the connection */
        self.conns.remove(token);
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.register(&self.server, self.token, EventSet::readable(), PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) {
        match evl.reregister(&self.server, self.token,
                             EventSet::readable(),
                             PollOpt::edge() | PollOpt::oneshot()) {
            Ok(_)   => {},
            Err(e)  => {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           }
        };
    }

    pub fn run(&mut self) {
        let mut evl = EventLoop::new().unwrap();
        self.register(&mut evl).ok();
        evl.run(self).unwrap();
    }
}
<commit_msg>make one super long line into two lines<commit_after>extern crate mio;
extern crate regex;

#[cfg(test)]
mod tests;

pub mod route;
pub mod request;
pub mod response;

use std::io::Result;
use std::io::prelude::*;
use std::net::ToSocketAddrs;
use std::collections::HashMap;
use std::collections::HashSet;
use mio::tcp::{TcpListener, TcpStream};
use mio::util::Slab;
use mio::*;

pub use route::*;
pub use request::*;
pub use response::*;

struct Client {
    sock:   TcpStream,
    token:  Token,
    events: EventSet,
    i_buf:  Vec<u8>,
    o_buf:  Vec<u8>,
}

impl Client {
    fn new(sock: TcpStream, token: Token) -> Client {
        Client {
            sock:   sock,
            token:  token,
            events: EventSet::hup(),
            i_buf:  Vec::new(),
            o_buf:  Vec::new(),
        }
    }

    fn receive(&mut self) -> Result<bool> {
        let mut buf: Vec<u8> = Vec::with_capacity(2048);

        match self.sock.try_read_buf(&mut buf) {
            Ok(size)  => {
                match size {
                    Some(_) => {
                        self.events.remove(EventSet::readable());
                        self.events.insert(EventSet::writable());
                        self.i_buf.extend(buf);
                        return Ok(true);
                    },
                    None    => {
                        return Ok(false);
                    },
                }
            },
            Err(e)  => {
                panic!("failed to read from socket! <token: {:?}> <error: {:?}>", self.token, e);
            },
        }

        Ok(false)
    }

    /* write the client's output buffer to the socket.
     *
     * the following return values mean:
     *  - Ok(true):  we can close the connection
     *  - Ok(false): keep listening for writeable event and continue next time
     *  - Err(e):    something dun fucked up
     */
    fn send(&mut self) -> Result<bool> {
        let out = self.o_buf.clone();

        match self.sock.write(&out.as_slice()) {
            Ok(sz)  => {
                if sz == self.o_buf.len() {
                    /* we did it! */
                    self.events.remove(EventSet::writable());
                    return Ok(true);
                } else {
                    self.o_buf = self.o_buf.split_off(sz);

                    return Ok(false);
                }
            },
            Err(e)  => {
                panic!("failed to write to socket! <token: {:?}> <error: {:?}>", self.token, e);
            }
        }

        Ok(false)
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        self.events.insert(EventSet::readable());

        evl.register(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.reregister(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to re-register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }
}

/* our primary object. similar interface to Flask, the
 * Python microframework. much faster, however! :)
 */
pub struct Canteen {
    routes:  HashMap<RouteDef, Route>,
    server:  TcpListener,
    token:   Token,
    conns:   Slab<Client>,
    default: fn(&Request) -> Response,
}

impl Handler for Canteen {
    type Timeout = ();
    type Message = u32;

    fn ready(&mut self, evl: &mut EventLoop<Canteen>, token: Token, events: EventSet) {
        if events.is_error() || events.is_hup() {
            self.reset_connection(token);
            return;
        }

        if events.is_readable() {
            if self.token == token {
                self.accept(evl);
            } else {
                self.readable(evl, token)
                    .and_then(|_| self.get_client(token)
                                      .reregister(evl))
                    .unwrap_or_else(|e| {
                        panic!("read event failed! <token: {:?}> <error: {:?}>", token, e);
                    });
            }

            return;
        }

        if events.is_writable() {
            match self.get_client(token).send() {
                Ok(true)    => { self.reset_connection(token); },
                Ok(false)   => { let _ = self.get_client(token).reregister(evl); },
                Err(_)      => { panic!("something really bad happened!"); },
            }
        }
    }
}

impl Canteen {
    pub fn new<A: ToSocketAddrs>(addr: A) -> Canteen {
        Canteen {
            routes:  HashMap::new(),
            server:  TcpListener::bind(&addr.to_socket_addrs().unwrap().next().unwrap()).unwrap(),
            token:   Token(1),
            conns:   Slab::new_starting_at(Token(2), 2048),
            default: Route::err_404,
        }
    }

    pub fn add_route(&mut self, path: &str, mlist: Vec<Method>,
                     handler: fn(&Request) -> Response) -> &mut Canteen {
        let mut methods: HashSet<Method> = HashSet::new();

        for m in mlist {
            methods.insert(m);
        }

        for m in methods {
            let rd = RouteDef {
                pathdef:    String::from(path),
                method:     m,
            };

            if self.routes.contains_key(&rd) {
                panic!("a route handler for {} has already been defined!", path);
            }

            self.routes.insert(rd, Route::new(&path, m, handler));
        }

        self
    }

    pub fn set_default(&mut self, handler: fn(&Request) -> Response) {
        self.default = handler;
    }

    fn get_client<'a>(&'a mut self, token: Token) -> &'a mut Client {
        &mut self.conns[token]
    }

    fn accept(&mut self, evl: &mut EventLoop<Canteen>) {
        let (sock, _) = match self.server.accept() {
            Ok(s)   => {
                match s {
                    Some(sock)  => sock,
                    None        => {
                        panic!("failed to accept new connection!");
                    }
                }
            },
            Err(e)  => {
                panic!("failed to accept new connection! <error: {:?}>", e);
            },
        };

        match self.conns.insert_with(|token| Client::new(sock, token)) {
            Some(token) => {
                match self.get_client(token).register(evl) {
                    Ok(_)   => {},
                    Err(e)  => {
                        panic!("failed to register client! <token: {:?}> <error: {:?}>", token, e);
                    },
                }
            },
            None        => {
                panic!("failed to add client connection!");
            },
        }

        self.reregister(evl);
    }

    fn handle_request(&self, req: &mut Request) -> Vec<u8> {
        let mut handler: fn(&Request) -> Response = self.default;

        for (_, route) in &self.routes {
            match (route).is_match(req) {
                true  => {
                    handler = route.handler;
                    req.params = route.parse(&req.path);
                    break;
                },
                false => continue,
            }
        }

        handler(req).gen_output()
    }

    fn readable(&mut self, evl: &mut EventLoop<Canteen>, token: Token) -> Result<bool> {
        match self.get_client(token).receive() {
            Ok(true)    => {
                let buf = self.get_client(token).i_buf.clone();
                let rqstr = String::from_utf8(buf).unwrap();
                let mut req = Request::from_str(&rqstr);
                let output = self.handle_request(&mut req);

                self.get_client(token).o_buf.extend(output);
            },
            Ok(false)   => {},
            Err(e)      => {
                panic!("message wasn't actually readable! <error: {:?}>", e);
            },
        };

        let _ = self.get_client(token).reregister(evl);

        Ok(true)
    }

    fn reset_connection(&mut self, token: Token) {
        /* kill the connection */
        self.conns.remove(token);
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.register(&self.server, self.token, EventSet::readable(), PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) {
        match evl.reregister(&self.server, self.token,
                             EventSet::readable(),
                             PollOpt::edge() | PollOpt::oneshot()) {
            Ok(_)   => {},
            Err(e)  => {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           }
        };
    }

    pub fn run(&mut self) {
        let mut evl = EventLoop::new().unwrap();
        self.register(&mut evl).ok();
        evl.run(self).unwrap();
    }
}
<|endoftext|>