<commit_before>// Copyright 2016 Google Inc.
//
// 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.
use crate::errors::*;
use crate::math::Cube;
use crate::proto;
use crate::read_write::{Encoding, PointIterator, PositionEncoding};
use crate::CURRENT_VERSION;
use cgmath::{EuclideanSpace, Matrix4, Point3};
use collision::{Aabb, Aabb3, Relation};
use fnv::FnvHashMap;
use num::clamp;
use std::cmp::Ordering;
use std::collections::BinaryHeap;
use std::io::{BufReader, Read};
use std::path::PathBuf;

use crate::iterator::{FilteredIterator, PointCloud, PointQuery};

mod generation;
pub use self::generation::{build_octree, build_octree_from_file};

mod factory;
pub use self::factory::OctreeFactory;

mod node;
pub use self::node::{to_node_proto, ChildIndex, Node, NodeId, NodeMeta};

mod octree_iterator;
pub use self::octree_iterator::NodeIdsIterator;

pub use crate::data_provider::{DataProvider, OnDiskDataProvider};

#[cfg(test)]
mod octree_test;

#[derive(Clone, Debug)]
pub struct OctreeMeta {
    pub resolution: f64,
    pub bounding_box: Aabb3<f64>,
}

impl OctreeMeta {
    pub fn encoding_for_node(&self, id: NodeId) -> Encoding {
        let bounding_cube = id.find_bounding_cube(&Cube::bounding(&self.bounding_box));
        let position_encoding = PositionEncoding::new(&bounding_cube, self.resolution);
        Encoding::ScaledToCube(
            bounding_cube.min().to_vec(),
            bounding_cube.edge_length(),
            position_encoding,
        )
    }
}

pub fn to_meta_proto(octree_meta: &OctreeMeta, nodes: Vec<proto::OctreeNode>) -> proto::Meta {
    let mut octree_proto = proto::OctreeMeta::new();
    octree_proto
        .mut_bounding_box()
        .mut_min()
        .set_x(octree_meta.bounding_box.min().x);
    octree_proto
        .mut_bounding_box()
        .mut_min()
        .set_y(octree_meta.bounding_box.min().y);
    octree_proto
        .mut_bounding_box()
        .mut_min()
        .set_z(octree_meta.bounding_box.min().z);
    octree_proto
        .mut_bounding_box()
        .mut_max()
        .set_x(octree_meta.bounding_box.max().x);
    octree_proto
        .mut_bounding_box()
        .mut_max()
        .set_y(octree_meta.bounding_box.max().y);
    octree_proto
        .mut_bounding_box()
        .mut_max()
        .set_z(octree_meta.bounding_box.max().z);
    octree_proto.set_resolution(octree_meta.resolution);

    let octree_nodes = ::protobuf::RepeatedField::<proto::OctreeNode>::from_vec(nodes);
    octree_proto.set_nodes(octree_nodes);

    let mut meta = proto::Meta::new();
    meta.set_version(CURRENT_VERSION);
    meta.set_octree(octree_proto);
    meta
}

// TODO(hrapp): something is funky here. "r" is smaller on screen than "r4" in many cases, though
// that is impossible.
fn project(m: &Matrix4<f64>, p: &Point3<f64>) -> Point3<f64> {
    let q = m * Point3::to_homogeneous(*p);
    Point3::from_homogeneous(q / q.w)
}

fn clip_point_to_hemicube(p: &Point3<f64>) -> Point3<f64> {
    Point3::new(clamp(p.x, -1., 1.), clamp(p.y, -1., 1.), clamp(p.z, 0., 1.))
}

// This method projects world points through the matrix and returns a value proportional to the
// size of the screen. We do not know the width and height of the frustum in pixels here, so the
// unit of the value is not really well defined.
// Ideally we'd need to know the aspect ration of width/height to make the returned value truly
// proportional to the size on the screen, but this parameter would need to be passed through to
// all API calls. I decided on relying on a 'good enough' metric instead which did not require the
// parameter.
fn relative_size_on_screen(bounding_cube: &Cube, matrix: &Matrix4<f64>) -> f64 {
    // z is unused here.
    let min = bounding_cube.min();
    let max = bounding_cube.max();
    let mut rv = Aabb3::new(
        clip_point_to_hemicube(&project(matrix, &min)),
        clip_point_to_hemicube(&project(matrix, &max)),
    );
    for p in &[
        Point3::new(max.x, min.y, min.z),
        Point3::new(min.x, max.y, min.z),
        Point3::new(max.x, max.y, min.z),
        Point3::new(min.x, min.y, max.z),
        Point3::new(max.x, min.y, max.z),
        Point3::new(min.x, max.y, max.z),
    ] {
        rv = rv.grow(clip_point_to_hemicube(&project(matrix, p)));
    }
    (rv.max().x - rv.min().x) * (rv.max().y - rv.min().y)
}

pub struct Octree {
    data_provider: Box<dyn DataProvider>,
    meta: OctreeMeta,
    nodes: FnvHashMap<NodeId, NodeMeta>,
}

#[derive(Debug)]
pub struct NodeData {
    pub meta: NodeMeta,
    pub position: Vec<u8>,
    pub color: Vec<u8>,
}

fn bounding_box_to_aabb(bounding_box: &proto::AxisAlignedCuboid) -> Aabb3<f64> {
    let min = bounding_box.min.clone().unwrap_or_else(|| {
        let deprecated_min = bounding_box.deprecated_min.clone().unwrap(); // Version 9
        let mut v = proto::Vector3d::new();
        v.set_x(f64::from(deprecated_min.x));
        v.set_y(f64::from(deprecated_min.y));
        v.set_z(f64::from(deprecated_min.z));
        v
    });
    let max = bounding_box.max.clone().unwrap_or_else(|| {
        let deprecated_max = bounding_box.deprecated_max.clone().unwrap(); // Version 9
        let mut v = proto::Vector3d::new();
        v.set_x(f64::from(deprecated_max.x));
        v.set_y(f64::from(deprecated_max.y));
        v.set_z(f64::from(deprecated_max.z));
        v
    });
    Aabb3::new(
        Point3::new(min.x, min.y, min.z),
        Point3::new(max.x, max.y, max.z),
    )
}

impl Octree {
    // TODO(sirver): This creates an object that is only partially usable.
    pub fn from_data_provider(data_provider: Box<dyn DataProvider>) -> Result<Self> {
        let meta_proto = data_provider.meta_proto()?;
        let (bounding_box, meta, nodes_proto) = match meta_proto.version {
            9 | 10 | 11 => {
                println!(
                    "Data is an older octree version: {}, current would be {}. \
                     If feasible, try upgrading this octree using `upgrade_octree`.",
                    meta_proto.version, CURRENT_VERSION
                );
                let bounding_box = bounding_box_to_aabb(meta_proto.get_deprecated_bounding_box());
                (
                    bounding_box,
                    OctreeMeta {
                        resolution: meta_proto.deprecated_resolution,
                        bounding_box,
                    },
                    meta_proto.get_deprecated_nodes(),
                )
            }
            CURRENT_VERSION => {
                if !meta_proto.has_octree() {
                    return Err(ErrorKind::InvalidInput("No octree meta found".to_string()).into());
                }
                let octree_meta = meta_proto.get_octree();
                let bounding_box = bounding_box_to_aabb(octree_meta.get_bounding_box());
                (
                    bounding_box,
                    OctreeMeta {
                        resolution: octree_meta.resolution,
                        bounding_box,
                    },
                    octree_meta.get_nodes(),
                )
            }
            _ => return Err(ErrorKind::InvalidVersion(meta_proto.version).into()),
        };

        let mut nodes = FnvHashMap::default();

        for node_proto in nodes_proto.iter() {
            let node_id = NodeId::from_proto(node_proto.id.as_ref().unwrap());
            nodes.insert(
                node_id,
                NodeMeta {
                    num_points: node_proto.num_points,
                    position_encoding: PositionEncoding::from_proto(node_proto.position_encoding)?,
                    bounding_cube: node_id.find_bounding_cube(&Cube::bounding(&bounding_box)),
                },
            );
        }

        Ok(Octree {
            meta,
            nodes,
            data_provider,
        })
    }

    pub fn to_meta_proto(&self) -> proto::Meta {
        let nodes: Vec<proto::OctreeNode> = self
            .nodes
            .iter()
            .map(|(id, node_meta)| {
                to_node_proto(&id, node_meta.num_points, &node_meta.position_encoding)
            })
            .collect();
        to_meta_proto(&self.meta, nodes)
    }

    pub fn get_visible_nodes(&self, projection_matrix: &Matrix4<f64>) -> Vec<NodeId> {
        let frustum = collision::Frustum::from_matrix4(*projection_matrix).unwrap();
        let mut open = BinaryHeap::new();
        maybe_push_node(
            &mut open,
            &self.nodes,
            Relation::Cross,
            Node::root_with_bounding_cube(Cube::bounding(&self.meta.bounding_box)),
            projection_matrix,
        );

        let mut visible = Vec::new();
        while let Some(current) = open.pop() {
            match current.relation {
                Relation::Cross => {
                    for child_index in 0..8 {
                        let child = current.node.get_child(ChildIndex::from_u8(child_index));
                        let child_relation = frustum.contains(&child.bounding_cube.to_aabb3());
                        if child_relation == Relation::Out {
                            continue;
                        }
                        maybe_push_node(
                            &mut open,
                            &self.nodes,
                            child_relation,
                            child,
                            projection_matrix,
                        );
                    }
                }
                Relation::In => {
                    // When the parent is fully in the frustum, so are the children.
                    for child_index in 0..8 {
                        maybe_push_node(
                            &mut open,
                            &self.nodes,
                            Relation::In,
                            current.node.get_child(ChildIndex::from_u8(child_index)),
                            projection_matrix,
                        );
                    }
                }
                Relation::Out => {
                    // This should never happen.
                    unreachable!();
                }
            };
            if !current.empty {
                visible.push(current.node.id);
            }
        }
        visible
    }

    pub fn get_node_data(&self, node_id: &NodeId) -> Result<NodeData> {
        // TODO(hrapp): If we'd randomize the points while writing, we could just read the
        // first N points instead of reading everything and skipping over a few.
        let mut position_color_reads = self
            .data_provider
            .data(&node_id.to_string(), &["position", "color"])?;

        let mut get_data = |node_attribute: &str, err: &str| -> Result<Vec<u8>> {
            let mut reader = BufReader::new(
                position_color_reads
                    .remove(node_attribute)
                    .ok_or_else(|| err)?,
            );
            let mut all_data = Vec::new();
            reader.read_to_end(&mut all_data).chain_err(|| err)?;
            Ok(all_data)
        };
        let position = get_data("position", "Could not read position")?;
        let color = get_data("color", "Could not read color")?;

        Ok(NodeData {
            position,
            color,
            meta: self.nodes[node_id].clone(),
        })
    }

    /// return the bounding box saved in meta
    pub fn bounding_box(&self) -> &Aabb3<f64> {
        &self.meta.bounding_box
    }
}

impl PointCloud for Octree {
    type Id = NodeId;
    type PointsIter = FilteredIterator;
    fn nodes_in_location(&self, query: &PointQuery) -> Vec<Self::Id> {
        let culling = query.get_point_culling();
        let filter_func = move |node_id: &NodeId, octree: &Octree| -> bool {
            let current = &octree.nodes[&node_id];
            culling.intersects_aabb3(&current.bounding_cube.to_aabb3())
        };
        NodeIdsIterator::new(&self, filter_func).collect()
    }

    fn encoding_for_node(&self, id: Self::Id) -> Encoding {
        self.meta.encoding_for_node(id)
    }

    fn points_in_node<'a>(
        &'a self,
        query: &PointQuery,
        node_id: NodeId,
    ) -> Result<FilteredIterator> {
        let culling = query.get_point_culling();
        let point_iterator = PointIterator::from_data_provider(
            &*self.data_provider,
            self.meta.encoding_for_node(node_id),
            &node_id,
            self.nodes[&node_id].num_points as usize,
        )?;
        Ok(FilteredIterator {
            culling,
            point_iterator,
        })
    }
}

struct OpenNode {
    node: Node,
    relation: Relation,
    size_on_screen: f64,
    empty: bool,
}

impl Ord for OpenNode {
    fn cmp(&self, other: &OpenNode) -> Ordering {
        if self.size_on_screen > other.size_on_screen {
            Ordering::Greater
        } else if self.size_on_screen < other.size_on_screen {
            Ordering::Less
        } else {
            Ordering::Equal
        }
    }
}

impl PartialOrd for OpenNode {
    fn partial_cmp(&self, other: &OpenNode) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for OpenNode {
    fn eq(&self, other: &OpenNode) -> bool {
        self.size_on_screen == other.size_on_screen
    }
}

impl Eq for OpenNode {}

#[inline]
fn maybe_push_node(
    v: &mut BinaryHeap<OpenNode>,
    nodes: &FnvHashMap<NodeId, NodeMeta>,
    relation: Relation,
    node: Node,
    projection_matrix: &Matrix4<f64>,
) {
    if let Some(meta) = nodes.get(&node.id) {
        let size_on_screen = relative_size_on_screen(&node.bounding_cube, projection_matrix);
        v.push(OpenNode {
            node,
            relation,
            size_on_screen,
            empty: meta.num_points == 0,
        });
    }
}

//  TODO(catevita): refactor function for octree factory
pub fn octree_from_directory(directory: impl Into<PathBuf>) -> Result<Box<Octree>> {
    let data_provider = OnDiskDataProvider {
        directory: directory.into(),
    };
    let octree = Octree::from_data_provider(Box::new(data_provider))?;
    Ok(Box::new(octree))
}
<commit_msg>Fix for clippy nightly. (#357)<commit_after>// Copyright 2016 Google Inc.
//
// 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.
use crate::errors::*;
use crate::math::Cube;
use crate::proto;
use crate::read_write::{Encoding, PointIterator, PositionEncoding};
use crate::CURRENT_VERSION;
use cgmath::{EuclideanSpace, Matrix4, Point3};
use collision::{Aabb, Aabb3, Relation};
use fnv::FnvHashMap;
use num::clamp;
use std::cmp::Ordering;
use std::collections::BinaryHeap;
use std::io::{BufReader, Read};
use std::path::PathBuf;

use crate::iterator::{FilteredIterator, PointCloud, PointQuery};

mod generation;
pub use self::generation::{build_octree, build_octree_from_file};

mod factory;
pub use self::factory::OctreeFactory;

mod node;
pub use self::node::{to_node_proto, ChildIndex, Node, NodeId, NodeMeta};

mod octree_iterator;
pub use self::octree_iterator::NodeIdsIterator;

pub use crate::data_provider::{DataProvider, OnDiskDataProvider};

#[cfg(test)]
mod octree_test;

#[derive(Clone, Debug)]
pub struct OctreeMeta {
    pub resolution: f64,
    pub bounding_box: Aabb3<f64>,
}

impl OctreeMeta {
    pub fn encoding_for_node(&self, id: NodeId) -> Encoding {
        let bounding_cube = id.find_bounding_cube(&Cube::bounding(&self.bounding_box));
        let position_encoding = PositionEncoding::new(&bounding_cube, self.resolution);
        Encoding::ScaledToCube(
            bounding_cube.min().to_vec(),
            bounding_cube.edge_length(),
            position_encoding,
        )
    }
}

pub fn to_meta_proto(octree_meta: &OctreeMeta, nodes: Vec<proto::OctreeNode>) -> proto::Meta {
    let mut octree_proto = proto::OctreeMeta::new();
    octree_proto
        .mut_bounding_box()
        .mut_min()
        .set_x(octree_meta.bounding_box.min().x);
    octree_proto
        .mut_bounding_box()
        .mut_min()
        .set_y(octree_meta.bounding_box.min().y);
    octree_proto
        .mut_bounding_box()
        .mut_min()
        .set_z(octree_meta.bounding_box.min().z);
    octree_proto
        .mut_bounding_box()
        .mut_max()
        .set_x(octree_meta.bounding_box.max().x);
    octree_proto
        .mut_bounding_box()
        .mut_max()
        .set_y(octree_meta.bounding_box.max().y);
    octree_proto
        .mut_bounding_box()
        .mut_max()
        .set_z(octree_meta.bounding_box.max().z);
    octree_proto.set_resolution(octree_meta.resolution);

    let octree_nodes = ::protobuf::RepeatedField::<proto::OctreeNode>::from_vec(nodes);
    octree_proto.set_nodes(octree_nodes);

    let mut meta = proto::Meta::new();
    meta.set_version(CURRENT_VERSION);
    meta.set_octree(octree_proto);
    meta
}

// TODO(hrapp): something is funky here. "r" is smaller on screen than "r4" in many cases, though
// that is impossible.
fn project(m: &Matrix4<f64>, p: &Point3<f64>) -> Point3<f64> {
    let q = m * Point3::to_homogeneous(*p);
    Point3::from_homogeneous(q / q.w)
}

fn clip_point_to_hemicube(p: &Point3<f64>) -> Point3<f64> {
    Point3::new(clamp(p.x, -1., 1.), clamp(p.y, -1., 1.), clamp(p.z, 0., 1.))
}

// This method projects world points through the matrix and returns a value proportional to the
// size of the screen. We do not know the width and height of the frustum in pixels here, so the
// unit of the value is not really well defined.
// Ideally we'd need to know the aspect ration of width/height to make the returned value truly
// proportional to the size on the screen, but this parameter would need to be passed through to
// all API calls. I decided on relying on a 'good enough' metric instead which did not require the
// parameter.
fn relative_size_on_screen(bounding_cube: &Cube, matrix: &Matrix4<f64>) -> f64 {
    // z is unused here.
    let min = bounding_cube.min();
    let max = bounding_cube.max();
    let mut rv = Aabb3::new(
        clip_point_to_hemicube(&project(matrix, &min)),
        clip_point_to_hemicube(&project(matrix, &max)),
    );
    for p in &[
        Point3::new(max.x, min.y, min.z),
        Point3::new(min.x, max.y, min.z),
        Point3::new(max.x, max.y, min.z),
        Point3::new(min.x, min.y, max.z),
        Point3::new(max.x, min.y, max.z),
        Point3::new(min.x, max.y, max.z),
    ] {
        rv = rv.grow(clip_point_to_hemicube(&project(matrix, p)));
    }
    (rv.max().x - rv.min().x) * (rv.max().y - rv.min().y)
}

pub struct Octree {
    data_provider: Box<dyn DataProvider>,
    meta: OctreeMeta,
    nodes: FnvHashMap<NodeId, NodeMeta>,
}

#[derive(Debug)]
pub struct NodeData {
    pub meta: NodeMeta,
    pub position: Vec<u8>,
    pub color: Vec<u8>,
}

fn bounding_box_to_aabb(bounding_box: &proto::AxisAlignedCuboid) -> Aabb3<f64> {
    let min = bounding_box.min.clone().unwrap_or_else(|| {
        let deprecated_min = bounding_box.deprecated_min.clone().unwrap(); // Version 9
        let mut v = proto::Vector3d::new();
        v.set_x(f64::from(deprecated_min.x));
        v.set_y(f64::from(deprecated_min.y));
        v.set_z(f64::from(deprecated_min.z));
        v
    });
    let max = bounding_box.max.clone().unwrap_or_else(|| {
        let deprecated_max = bounding_box.deprecated_max.clone().unwrap(); // Version 9
        let mut v = proto::Vector3d::new();
        v.set_x(f64::from(deprecated_max.x));
        v.set_y(f64::from(deprecated_max.y));
        v.set_z(f64::from(deprecated_max.z));
        v
    });
    Aabb3::new(
        Point3::new(min.x, min.y, min.z),
        Point3::new(max.x, max.y, max.z),
    )
}

impl Octree {
    // TODO(sirver): This creates an object that is only partially usable.
    pub fn from_data_provider(data_provider: Box<dyn DataProvider>) -> Result<Self> {
        let meta_proto = data_provider.meta_proto()?;
        let (bounding_box, meta, nodes_proto) = match meta_proto.version {
            9 | 10 | 11 => {
                println!(
                    "Data is an older octree version: {}, current would be {}. \
                     If feasible, try upgrading this octree using `upgrade_octree`.",
                    meta_proto.version, CURRENT_VERSION
                );
                let bounding_box = bounding_box_to_aabb(meta_proto.get_deprecated_bounding_box());
                (
                    bounding_box,
                    OctreeMeta {
                        resolution: meta_proto.deprecated_resolution,
                        bounding_box,
                    },
                    meta_proto.get_deprecated_nodes(),
                )
            }
            CURRENT_VERSION => {
                if !meta_proto.has_octree() {
                    return Err(ErrorKind::InvalidInput("No octree meta found".to_string()).into());
                }
                let octree_meta = meta_proto.get_octree();
                let bounding_box = bounding_box_to_aabb(octree_meta.get_bounding_box());
                (
                    bounding_box,
                    OctreeMeta {
                        resolution: octree_meta.resolution,
                        bounding_box,
                    },
                    octree_meta.get_nodes(),
                )
            }
            _ => return Err(ErrorKind::InvalidVersion(meta_proto.version).into()),
        };

        let mut nodes = FnvHashMap::default();

        for node_proto in nodes_proto.iter() {
            let node_id = NodeId::from_proto(node_proto.id.as_ref().unwrap());
            nodes.insert(
                node_id,
                NodeMeta {
                    num_points: node_proto.num_points,
                    position_encoding: PositionEncoding::from_proto(node_proto.position_encoding)?,
                    bounding_cube: node_id.find_bounding_cube(&Cube::bounding(&bounding_box)),
                },
            );
        }

        Ok(Octree {
            meta,
            nodes,
            data_provider,
        })
    }

    pub fn to_meta_proto(&self) -> proto::Meta {
        let nodes: Vec<proto::OctreeNode> = self
            .nodes
            .iter()
            .map(|(id, node_meta)| {
                to_node_proto(&id, node_meta.num_points, &node_meta.position_encoding)
            })
            .collect();
        to_meta_proto(&self.meta, nodes)
    }

    pub fn get_visible_nodes(&self, projection_matrix: &Matrix4<f64>) -> Vec<NodeId> {
        let frustum = collision::Frustum::from_matrix4(*projection_matrix).unwrap();
        let mut open = BinaryHeap::new();
        maybe_push_node(
            &mut open,
            &self.nodes,
            Relation::Cross,
            Node::root_with_bounding_cube(Cube::bounding(&self.meta.bounding_box)),
            projection_matrix,
        );

        let mut visible = Vec::new();
        while let Some(current) = open.pop() {
            match current.relation {
                Relation::Cross => {
                    for child_index in 0..8 {
                        let child = current.node.get_child(ChildIndex::from_u8(child_index));
                        let child_relation = frustum.contains(&child.bounding_cube.to_aabb3());
                        if child_relation == Relation::Out {
                            continue;
                        }
                        maybe_push_node(
                            &mut open,
                            &self.nodes,
                            child_relation,
                            child,
                            projection_matrix,
                        );
                    }
                }
                Relation::In => {
                    // When the parent is fully in the frustum, so are the children.
                    for child_index in 0..8 {
                        maybe_push_node(
                            &mut open,
                            &self.nodes,
                            Relation::In,
                            current.node.get_child(ChildIndex::from_u8(child_index)),
                            projection_matrix,
                        );
                    }
                }
                Relation::Out => {
                    // This should never happen.
                    unreachable!();
                }
            };
            if !current.empty {
                visible.push(current.node.id);
            }
        }
        visible
    }

    pub fn get_node_data(&self, node_id: &NodeId) -> Result<NodeData> {
        // TODO(hrapp): If we'd randomize the points while writing, we could just read the
        // first N points instead of reading everything and skipping over a few.
        let mut position_color_reads = self
            .data_provider
            .data(&node_id.to_string(), &["position", "color"])?;

        let mut get_data = |node_attribute: &str, err: &str| -> Result<Vec<u8>> {
            let mut reader = BufReader::new(
                position_color_reads
                    .remove(node_attribute)
                    .ok_or_else(|| err)?,
            );
            let mut all_data = Vec::new();
            reader.read_to_end(&mut all_data).chain_err(|| err)?;
            Ok(all_data)
        };
        let position = get_data("position", "Could not read position")?;
        let color = get_data("color", "Could not read color")?;

        Ok(NodeData {
            position,
            color,
            meta: self.nodes[node_id].clone(),
        })
    }

    /// return the bounding box saved in meta
    pub fn bounding_box(&self) -> &Aabb3<f64> {
        &self.meta.bounding_box
    }
}

impl PointCloud for Octree {
    type Id = NodeId;
    type PointsIter = FilteredIterator;
    fn nodes_in_location(&self, query: &PointQuery) -> Vec<Self::Id> {
        let culling = query.get_point_culling();
        let filter_func = move |node_id: &NodeId, octree: &Octree| -> bool {
            let current = &octree.nodes[&node_id];
            culling.intersects_aabb3(&current.bounding_cube.to_aabb3())
        };
        NodeIdsIterator::new(&self, filter_func).collect()
    }

    fn encoding_for_node(&self, id: Self::Id) -> Encoding {
        self.meta.encoding_for_node(id)
    }

    fn points_in_node<'a>(
        &'a self,
        query: &PointQuery,
        node_id: NodeId,
    ) -> Result<FilteredIterator> {
        let culling = query.get_point_culling();
        let point_iterator = PointIterator::from_data_provider(
            &*self.data_provider,
            self.meta.encoding_for_node(node_id),
            &node_id,
            self.nodes[&node_id].num_points as usize,
        )?;
        Ok(FilteredIterator {
            culling,
            point_iterator,
        })
    }
}

struct OpenNode {
    node: Node,
    relation: Relation,
    size_on_screen: f64,
    empty: bool,
}

impl Ord for OpenNode {
    fn cmp(&self, other: &OpenNode) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

impl PartialOrd for OpenNode {
    fn partial_cmp(&self, other: &OpenNode) -> Option<Ordering> {
        self.size_on_screen.partial_cmp(&other.size_on_screen)
    }
}

impl PartialEq for OpenNode {
    fn eq(&self, other: &OpenNode) -> bool {
        self.size_on_screen == other.size_on_screen
    }
}

impl Eq for OpenNode {}

#[inline]
fn maybe_push_node(
    v: &mut BinaryHeap<OpenNode>,
    nodes: &FnvHashMap<NodeId, NodeMeta>,
    relation: Relation,
    node: Node,
    projection_matrix: &Matrix4<f64>,
) {
    if let Some(meta) = nodes.get(&node.id) {
        let size_on_screen = relative_size_on_screen(&node.bounding_cube, projection_matrix);
        v.push(OpenNode {
            node,
            relation,
            size_on_screen,
            empty: meta.num_points == 0,
        });
    }
}

//  TODO(catevita): refactor function for octree factory
pub fn octree_from_directory(directory: impl Into<PathBuf>) -> Result<Box<Octree>> {
    let data_provider = OnDiskDataProvider {
        directory: directory.into(),
    };
    let octree = Octree::from_data_provider(Box::new(data_provider))?;
    Ok(Box::new(octree))
}
<|endoftext|>


<commit_before>//! An oscillator that generates periodic waveforms.

#![experimental]

use std::f32::consts::PI;
use std::num::FloatMath;
use std::rand;

use core::{SAMPLE_RATE, AudioDevice, Sample, Time};
use core::components::OutputArray;

use self::AntialiasType::PolyBlep;
use self::Waveform::{Sine, Saw, Square, Tri, WhiteNoise, PulseTrain};

/// Antialiasing method for certain waveforms.
///
/// Aliased waveforms will use naive methods that produce aliasing.
/// PolyBlep uses offsets to round off sharp edges and reduce aliasing.
pub enum AntialiasType {
    Aliased, PolyBlep
}

/// Oscillator waveforms.
///
/// Saw, Square, and Tri provide both aliased waveforms, and antialiased
/// waveforms using PolyBLEP. Aliased waveformsare useful for control signals,
/// but not for raw audio signals. For audible signals, instead used the
/// corresponding PolyBlep waveforms.
pub enum Waveform {
    Sine,
    Saw(AntialiasType),
    Square(AntialiasType),
    Tri(AntialiasType),
    WhiteNoise,
    PulseTrain
}

/// Generates a periodic waveform.
pub struct Oscillator {
    /// The oscillator output array, with a single output channel.
    pub output: OutputArray,

    waveform: Waveform,
    phase: f32,
    phase_delta: f32,
    last_sample: Sample,
}

impl Oscillator {
    /// Returns an oscillator with the specified waveform at the specified
    /// frequency.
    pub fn new(waveform: Waveform, freq: f32) -> Oscillator {
        Oscillator {
            output: OutputArray::new(1),
            waveform: waveform,
            phase: 0.0,
            phase_delta: freq*2.0*PI/(SAMPLE_RATE as f32),
            last_sample: 0.0
        }
    }
}

impl AudioDevice for Oscillator {
    fn tick(&mut self, _t: Time) {
        // Tick the phase
        self.phase += self.phase_delta;
        if self.phase >= 2.0*PI {
            self.phase -= 2.0*PI;
        }

        // Compute the next sample
        let s: Sample = match self.waveform {
            Sine => self.phase.sin(),
            Saw(aa) => {
                let mut out = self.phase/PI -1.0;
                match aa {
                    PolyBlep => {
                        out -= poly_belp_offset(self.phase/(2.0*PI),
                                                self.phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Square(aa) => {
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                self.phase_delta/(2.0*PI));
                        out -= poly_belp_offset(fmod(self.phase/(2.0*PI)+0.5,
                                                     1.0),
                                                self.phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Tri(aa) => {
                // Compute a square wave signal
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                self.phase_delta/(2.0*PI));
                        out -= poly_belp_offset(fmod(self.phase/(2.0*PI)+0.5,
                                                     1.0),
                                                self.phase_delta/(2.0*PI));
                    },
                    _ => ()
                }

                // Perform leaky integration
                self.phase_delta*out + (1.0-self.phase_delta)*self.last_sample
            },
            WhiteNoise => 2.0*rand::random::<f32>() - 1.0,
            PulseTrain => {
                // If we wrapped around...
                if self.phase < self.phase_delta {
                    1.0
                } else {
                    0.0
                }
            }
        };

        // Push the sample out
        self.output.push(0, s);
    }
}

/// Floating point modulus
fn fmod(n: f32, base: f32) -> f32 {
    assert!(base > 0.0);
    let mut out = n;
    while out < 0.0 {
        out += base;
    }
    while out >= base {
        out -= base;
    }
    out
}

/// Computes an offset for PolyBLEP antialiasing
///
/// `t` should be the current waveform phase, normalized
/// `dt` should be the change in phase for one sample time, normalized
fn poly_belp_offset(t: f32, dt: f32) -> f32 {
    if t < dt { // t ~= 0
        let t = dt;
        -t*t + 2.0*t - 1.0
    } else if t > 1.0-dt { // t ~= 1
        let t = (t-1.0) / dt;
        t*t + 2.0*t + 1.0
    } else {
        0.0
    }
}

// A couple of basic unit tests...
#[cfg(test)]
mod test {
    use core::util::flt_eq;
    static EPSILON: f32 = 1e-6;

    /// Tests fmod with many values
    #[test]
    fn test_fmod() {
        use super::fmod;

        // negatives...
        assert!(flt_eq(fmod(-1.5, 1.0), 0.5, EPSILON));
        assert!(flt_eq(fmod(-1.0, 1.0), 0.0, EPSILON));
        assert!(flt_eq(fmod(-0.5, 1.0), 0.5, EPSILON));

        // in range...
        assert!(flt_eq(fmod(0.0, 1.0), 0.0, EPSILON));
        assert!(flt_eq(fmod(0.5, 1.0), 0.5, EPSILON));
        assert!(flt_eq(fmod(0.9, 1.0), 0.9, EPSILON));

        // above...
        assert!(flt_eq(fmod(1.0, 1.0), 0.0, EPSILON));
        assert!(flt_eq(fmod(1.5, 1.0), 0.5, EPSILON));
        assert!(flt_eq(fmod(2.0, 1.0), 0.0, EPSILON));
        assert!(flt_eq(fmod(2.5, 1.0), 0.5, EPSILON));

        // different base...
        assert!(flt_eq(fmod(-0.5, 0.9), 0.4, EPSILON));
        assert!(flt_eq(fmod(0.0, 0.9), 0.0, EPSILON));
        assert!(flt_eq(fmod(0.5, 0.9), 0.5, EPSILON));
        assert!(flt_eq(fmod(0.9, 0.9), 0.0, EPSILON));
        assert!(flt_eq(fmod(1.0, 0.9), 0.1, EPSILON));
    }

    /// Tests square wave
    #[test]
    fn test_naive_square() {
        use super::Oscillator;
        use core::AudioDevice;
        let mut osc = Oscillator::new(super::Square(super::Aliased), 4410.0);

        osc.tick(0); assert!(osc.output.get(0, 0).unwrap() == 1.0);
        osc.tick(1); assert!(osc.output.get(0, 1).unwrap() == 1.0);
        osc.tick(2); assert!(osc.output.get(0, 2).unwrap() == 1.0);
        osc.tick(3); assert!(osc.output.get(0, 3).unwrap() == 1.0);
        osc.tick(4); assert!(osc.output.get(0, 4).unwrap() == -1.0);
        osc.tick(5); assert!(osc.output.get(0, 5).unwrap() == -1.0);
        osc.tick(6); assert!(osc.output.get(0, 6).unwrap() == -1.0);
        osc.tick(7); assert!(osc.output.get(0, 7).unwrap() == -1.0);
        osc.tick(8); assert!(osc.output.get(0, 8).unwrap() == -1.0);
    }

    /// Tests saw wave
    #[test]
    fn test_naive_saw() {
        use super::Oscillator;
        use core::AudioDevice;
        let mut osc = Oscillator::new(super::Saw(super::Aliased), 4410.0);

        osc.tick(0); assert!(flt_eq(osc.output.get(0, 0).unwrap(),
                                    -0.8, EPSILON));
        osc.tick(1); assert!(flt_eq(osc.output.get(0, 1).unwrap(),
                                    -0.6, EPSILON));
        osc.tick(2); assert!(flt_eq(osc.output.get(0, 2).unwrap(),
                                    -0.4, EPSILON));
        osc.tick(3); assert!(flt_eq(osc.output.get(0, 3).unwrap(),
                                    -0.2, EPSILON));
        osc.tick(4); assert!(flt_eq(osc.output.get(0, 4).unwrap(),
                                    0.0, EPSILON));
        osc.tick(5); assert!(flt_eq(osc.output.get(0, 5).unwrap(),
                                    0.2, EPSILON));
        osc.tick(6); assert!(flt_eq(osc.output.get(0, 6).unwrap(),
                                    0.4, EPSILON));
        osc.tick(7); assert!(flt_eq(osc.output.get(0, 7).unwrap(),
                                    0.6, EPSILON));
        osc.tick(8); assert!(flt_eq(osc.output.get(0, 8).unwrap(),
                                    0.8, EPSILON));
    }
}
<commit_msg>Fixes rustc changes for tests<commit_after>//! An oscillator that generates periodic waveforms.

#![experimental]

use std::f32::consts::PI;
use std::num::FloatMath;
use std::rand;

use core::{SAMPLE_RATE, AudioDevice, Sample, Time};
use core::components::OutputArray;

use self::AntialiasType::PolyBlep;
use self::Waveform::{Sine, Saw, Square, Tri, WhiteNoise, PulseTrain};

/// Antialiasing method for certain waveforms.
///
/// Aliased waveforms will use naive methods that produce aliasing.
/// PolyBlep uses offsets to round off sharp edges and reduce aliasing.
pub enum AntialiasType {
    Aliased, PolyBlep
}

/// Oscillator waveforms.
///
/// Saw, Square, and Tri provide both aliased waveforms, and antialiased
/// waveforms using PolyBLEP. Aliased waveformsare useful for control signals,
/// but not for raw audio signals. For audible signals, instead used the
/// corresponding PolyBlep waveforms.
pub enum Waveform {
    Sine,
    Saw(AntialiasType),
    Square(AntialiasType),
    Tri(AntialiasType),
    WhiteNoise,
    PulseTrain
}

/// Generates a periodic waveform.
pub struct Oscillator {
    /// The oscillator output array, with a single output channel.
    pub output: OutputArray,

    waveform: Waveform,
    phase: f32,
    phase_delta: f32,
    last_sample: Sample,
}

impl Oscillator {
    /// Returns an oscillator with the specified waveform at the specified
    /// frequency.
    pub fn new(waveform: Waveform, freq: f32) -> Oscillator {
        Oscillator {
            output: OutputArray::new(1),
            waveform: waveform,
            phase: 0.0,
            phase_delta: freq*2.0*PI/(SAMPLE_RATE as f32),
            last_sample: 0.0
        }
    }
}

impl AudioDevice for Oscillator {
    fn tick(&mut self, _t: Time) {
        // Tick the phase
        self.phase += self.phase_delta;
        if self.phase >= 2.0*PI {
            self.phase -= 2.0*PI;
        }

        // Compute the next sample
        let s: Sample = match self.waveform {
            Sine => self.phase.sin(),
            Saw(aa) => {
                let mut out = self.phase/PI -1.0;
                match aa {
                    PolyBlep => {
                        out -= poly_belp_offset(self.phase/(2.0*PI),
                                                self.phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Square(aa) => {
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                self.phase_delta/(2.0*PI));
                        out -= poly_belp_offset(fmod(self.phase/(2.0*PI)+0.5,
                                                     1.0),
                                                self.phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Tri(aa) => {
                // Compute a square wave signal
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                self.phase_delta/(2.0*PI));
                        out -= poly_belp_offset(fmod(self.phase/(2.0*PI)+0.5,
                                                     1.0),
                                                self.phase_delta/(2.0*PI));
                    },
                    _ => ()
                }

                // Perform leaky integration
                self.phase_delta*out + (1.0-self.phase_delta)*self.last_sample
            },
            WhiteNoise => 2.0*rand::random::<f32>() - 1.0,
            PulseTrain => {
                // If we wrapped around...
                if self.phase < self.phase_delta {
                    1.0
                } else {
                    0.0
                }
            }
        };

        // Push the sample out
        self.output.push(0, s);
    }
}

/// Floating point modulus
fn fmod(n: f32, base: f32) -> f32 {
    assert!(base > 0.0);
    let mut out = n;
    while out < 0.0 {
        out += base;
    }
    while out >= base {
        out -= base;
    }
    out
}

/// Computes an offset for PolyBLEP antialiasing
///
/// `t` should be the current waveform phase, normalized
/// `dt` should be the change in phase for one sample time, normalized
fn poly_belp_offset(t: f32, dt: f32) -> f32 {
    if t < dt { // t ~= 0
        let t = dt;
        -t*t + 2.0*t - 1.0
    } else if t > 1.0-dt { // t ~= 1
        let t = (t-1.0) / dt;
        t*t + 2.0*t + 1.0
    } else {
        0.0
    }
}

// A couple of basic unit tests...
#[cfg(test)]
mod test {
    use core::util::flt_eq;
    static EPSILON: f32 = 1e-6;

    /// Tests fmod with many values
    #[test]
    fn test_fmod() {
        use super::fmod;

        // negatives...
        assert!(flt_eq(fmod(-1.5, 1.0), 0.5, EPSILON));
        assert!(flt_eq(fmod(-1.0, 1.0), 0.0, EPSILON));
        assert!(flt_eq(fmod(-0.5, 1.0), 0.5, EPSILON));

        // in range...
        assert!(flt_eq(fmod(0.0, 1.0), 0.0, EPSILON));
        assert!(flt_eq(fmod(0.5, 1.0), 0.5, EPSILON));
        assert!(flt_eq(fmod(0.9, 1.0), 0.9, EPSILON));

        // above...
        assert!(flt_eq(fmod(1.0, 1.0), 0.0, EPSILON));
        assert!(flt_eq(fmod(1.5, 1.0), 0.5, EPSILON));
        assert!(flt_eq(fmod(2.0, 1.0), 0.0, EPSILON));
        assert!(flt_eq(fmod(2.5, 1.0), 0.5, EPSILON));

        // different base...
        assert!(flt_eq(fmod(-0.5, 0.9), 0.4, EPSILON));
        assert!(flt_eq(fmod(0.0, 0.9), 0.0, EPSILON));
        assert!(flt_eq(fmod(0.5, 0.9), 0.5, EPSILON));
        assert!(flt_eq(fmod(0.9, 0.9), 0.0, EPSILON));
        assert!(flt_eq(fmod(1.0, 0.9), 0.1, EPSILON));
    }

    /// Tests square wave
    #[test]
    fn test_naive_square() {
        use super::{AntialiasType, Waveform, Oscillator};
        use core::AudioDevice;
        let mut osc = Oscillator::new(Waveform::Square(AntialiasType::Aliased),
                                      4410.0);

        osc.tick(0); assert!(osc.output.get(0, 0).unwrap() == 1.0);
        osc.tick(1); assert!(osc.output.get(0, 1).unwrap() == 1.0);
        osc.tick(2); assert!(osc.output.get(0, 2).unwrap() == 1.0);
        osc.tick(3); assert!(osc.output.get(0, 3).unwrap() == 1.0);
        osc.tick(4); assert!(osc.output.get(0, 4).unwrap() == -1.0);
        osc.tick(5); assert!(osc.output.get(0, 5).unwrap() == -1.0);
        osc.tick(6); assert!(osc.output.get(0, 6).unwrap() == -1.0);
        osc.tick(7); assert!(osc.output.get(0, 7).unwrap() == -1.0);
        osc.tick(8); assert!(osc.output.get(0, 8).unwrap() == -1.0);
    }

    /// Tests saw wave
    #[test]
    fn test_naive_saw() {
        use super::{AntialiasType, Waveform, Oscillator};
        use core::AudioDevice;
        let mut osc = Oscillator::new(Waveform::Saw(AntialiasType::Aliased),
                                      4410.0);

        osc.tick(0); assert!(flt_eq(osc.output.get(0, 0).unwrap(),
                                    -0.8, EPSILON));
        osc.tick(1); assert!(flt_eq(osc.output.get(0, 1).unwrap(),
                                    -0.6, EPSILON));
        osc.tick(2); assert!(flt_eq(osc.output.get(0, 2).unwrap(),
                                    -0.4, EPSILON));
        osc.tick(3); assert!(flt_eq(osc.output.get(0, 3).unwrap(),
                                    -0.2, EPSILON));
        osc.tick(4); assert!(flt_eq(osc.output.get(0, 4).unwrap(),
                                    0.0, EPSILON));
        osc.tick(5); assert!(flt_eq(osc.output.get(0, 5).unwrap(),
                                    0.2, EPSILON));
        osc.tick(6); assert!(flt_eq(osc.output.get(0, 6).unwrap(),
                                    0.4, EPSILON));
        osc.tick(7); assert!(flt_eq(osc.output.get(0, 7).unwrap(),
                                    0.6, EPSILON));
        osc.tick(8); assert!(flt_eq(osc.output.get(0, 8).unwrap(),
                                    0.8, EPSILON));
    }
}
<|endoftext|>


<commit_before>macro_rules! push {
    ($s:ident, $t:expr) => {{
        // println!("parser push: {:?}", $t);
        Ok($s.vm.borrow_mut().alloc($t))
    }}
}

mod error;

use std::rc::Rc;
use std::cell::RefCell;
use std::usize::MAX;
use core::*;
use lexer::*;
use self::error::Error;

const UNIT_INDX: usize = 5;

pub struct Parser<'a> {
    lexer: Lexer<'a, 'a>,
    vm: Rc<RefCell<Heliqs>>,
    // state: State,
    current_token: RefCell<CurrentToken>,
    // aexp_tokens: Vec<Vec<Tokn>>,

    lookahead: [CurrentToken; 2],
    p: usize,
}

#[derive(Eq, PartialEq, Clone, Debug)]
enum CurrentToken {
    SOT, // Start Of Tokens
    Has(Tokn),
    EOT, // End Of Tokens
}

impl<'a> Parser<'a> {
    pub fn new(lexer: Lexer<'a, 'a>, vm: Rc<RefCell<Heliqs>>) -> Self {
        let mut parser = Parser {
            lexer: lexer,
            vm: vm,
            // state: State::Aexp,
            current_token: RefCell::new(CurrentToken::SOT),
            // aexp_tokens: vec![vec![]],
            lookahead: [CurrentToken::SOT, CurrentToken::SOT],
            p: 1, // 0にはCurrentToken::SOTを入れることが固定で決まっているので、consumeを開始するのは1から
        };

        parser.consume_token();

        parser
    }

    // Unitは常に1つにする(index固定)
    fn add_unit(&mut self) {
        let _unit = self.vm.borrow_mut().alloc(Epiq::Unit);
    }

    fn add_prim(&mut self, name: &str) {
        let prim = self.vm.borrow_mut().alloc(Epiq::Prim(name.to_string()));
        self.vm.borrow_mut().define(name, prim);
    }

    pub fn parse(&mut self) {

        self.add_prim("decr");
        self.add_prim("ltoreq");
        self.add_prim("eq");
        self.add_prim("plus");
        self.add_prim("minus");

        self.add_unit();

        self.consume_token();

        let _ = self.parse_aexp();
    }

    fn set_current_token(&mut self, t: CurrentToken) {
        // let mut token = self.current_token.borrow_mut();
        // *token = t;

        self.lookahead[self.p] = t;
        self.p = 1 - self.p;
    }

    // ひどい名前
    // 指定された番目のCurrentTokenを返す
    //
    fn index_from_index(&self, i: usize) -> usize {
        // i == 0 -> self.p
        // i == 1 -> 1 - self.p
        match i {
            0 => self.p,
            1 => 1 - self.p,
            _ => MAX,
        }
    }

    fn get_token(&self, i: usize) -> CurrentToken {
        self.lookahead[self.index_from_index(i)].clone()
    }

    fn get_current_token(&self) -> CurrentToken {
        // self.current_token.borrow().clone()
        // self.lookahead[self.p].clone()
        self.get_token(0)
    }

    fn consume_token(&mut self) {
        let res = self.lexer.tokenize();
        match res {
            TokenizeResult::Ok(t) => self.set_current_token(CurrentToken::Has(t)),
            TokenizeResult::Err(_e) => {},
            TokenizeResult::EOF => self.set_current_token(CurrentToken::EOT),
        }
    }

    fn parse_aexp(&mut self) -> Result<usize, Error> {
        let res = self.get_current_token();

        match res {
            // 中置記法の判断をする
            CurrentToken::Has(Tokn::Chvc(_)) |
            CurrentToken::Has(Tokn::Nmbr(_))
            if self.get_token(1) == CurrentToken::Has(Tokn::Bang) => {
                self.parse_apply()
            },

            // LL(1)の範囲内
            CurrentToken::Has(Tokn::Atsm) => {
                self.consume_token();
                self.parse_resolve()
            },

            CurrentToken::Has(Tokn::Sgqt) => {
                self.consume_token();
                self.parse_otag(Tokn::Sgqt)
            },

            CurrentToken::Has(Tokn::Pipe) => {
                self.consume_token();
                self.parse_otag(Tokn::Pipe)
            },
            CurrentToken::Has(Tokn::Crrt) => {
                self.consume_token();
                self.parse_otag(Tokn::Crrt)
            },
            CurrentToken::Has(Tokn::Smcl) => {
                self.consume_token();
                Ok(UNIT_INDX)
            }
            CurrentToken::Has(Tokn::Lbkt) => {
                self.consume_token();
                self.parse_list()
            },
            CurrentToken::Has(Tokn::Dbqt) => {
                self.consume_token();
                self.parse_text()
            },

            _ => {
                self.parse_literal()
                // // 中置記法の判断をする
                // let token0 = self.get_token(0);
                // match token0 {
                //     CurrentToken::Has(Tokn::Chvc(_)) |
                //     CurrentToken::Has(Tokn::Nmbr(_))
                //     if self.get_token(1) == CurrentToken::Has(Tokn::Bang) => {
                //         self.parse_apply()
                //     }
                //     _ => self.parse_literal()
                // }
            },
        }
    }

    fn parse_resolve(&mut self) -> Result<usize, Error> {
        // let pidx = (self.parse_aexp())?;
        let qidx = (self.parse_literal())?;
        let id = self.vm.borrow_mut().alloc(Epiq::Rslv(UNIT_INDX, qidx));
        push!(self, Epiq::Eval(UNIT_INDX, id))
    }

    // Pipe QTag Pval QVal
    fn parse_otag(&mut self, tokn: Tokn) -> Result<usize, Error> {
        let current_token = self.get_current_token();
        match current_token {
            CurrentToken::Has(Tokn::Otag(ref otag)) => {
                self.consume_token();

                match tokn {
                    Tokn::Pipe => {
                        let pidx = (self.parse_aexp())?;
                        let qidx = (self.parse_aexp())?;
                        self.match_otag(pidx, qidx, otag)
                    },
                    Tokn::Crrt => {
                        match otag.as_ref() {
                            // ^Tと^Fは特別扱い
                            "T" => push!(self, Epiq::Tval),
                            "F" => push!(self, Epiq::Fval),
                            _ =>  {
                                // 現在は^Tか^Fしか認めていないが、将来のため
                                let pidx = (self.parse_aexp())?;
                                let qidx = (self.parse_aexp())?;
                                push!(self, Epiq::Mpiq{o: otag.clone(), p: pidx, q: qidx})
                            },
                        }
                    },
                    Tokn::Sgqt => {
                        // 引数は一つ、それをqとみなす
                        let qidx = (self.parse_aexp())?;
                        self.match_otag(UNIT_INDX, qidx, otag)
                    },
                    _ => Err(Error::UnknownError(255)),
                }
            },

            CurrentToken::Has(ref t) => Err(Error::TokenError(t.clone())),
            _ => Err(Error::UnknownError(1)),
        }
    }

    fn match_otag(&mut self, pidx: NodeId, qidx: NodeId, otag: &str) -> Result<usize, Error> {
        match otag {
            ">" => push!(self, Epiq::Eval(pidx, qidx)),
            ":" => push!(self, Epiq::Lpiq(pidx, qidx)),
            "!" => push!(self, Epiq::Appl(pidx, qidx)),
            "@" => push!(self, Epiq::Rslv(pidx, qidx)),
            "?" => push!(self, Epiq::Cond(pidx, qidx)),
            "%" => push!(self, Epiq::Envn(pidx, qidx)),
            "#" => push!(self, Epiq::Bind(pidx, qidx)),
            "." => push!(self, Epiq::Accs(pidx, qidx)),
            r"\" => push!(self, Epiq::Lmbd(pidx, qidx)),

            _ => {
                push!(self, Epiq::Tpiq{o: otag.to_string(), p: pidx, q: qidx})
            },
        }
    }

    fn parse_list(&mut self) -> Result<usize, Error> {
        let current_token = self.get_current_token();
        // 閉じbracketが出るまで再帰呼出
        match current_token {
            CurrentToken::Has(Tokn::Rbkt) => {
                self.consume_token();
                push!(self, Epiq::Unit)
            },
            _ => {
                let pidx = (self.parse_aexp())?;
                let qidx = (self.parse_list())?;
                push!(self, Epiq::Lpiq(pidx, qidx))
            }
        }
    }

    fn parse_text(&mut self) -> Result<usize, Error> {
        let current_token1 = self.get_current_token();
        match current_token1 {
            CurrentToken::Has(Tokn::Chvc(ref s)) => {
                self.consume_token();
                let current_token2 = self.get_current_token();
                match current_token2 {
                    CurrentToken::Has(Tokn::Dbqt) => {
                        self.consume_token();
                        push!(self, Epiq::Text(s.clone()))
                    },
                    _ => Err(Error::UnknownError(13)),
                }
            },
            _ => Err(Error::UnknownError(12)),
        }
    }

    fn parse_literal(&mut self) -> Result<usize, Error> {
        let current_token = self.get_current_token();
        match current_token {
            CurrentToken::Has(Tokn::Chvc(ref s)) => {
                self.consume_token();
                push!(self, Epiq::Name(s.clone()))
            },
            CurrentToken::Has(Tokn::Nmbr(ref s)) => {
                self.consume_token();
                push!(self, Epiq::Uit8(s.parse::<i64>().unwrap()))
            },
            _ => Err(Error::UnknownError(10)),
        }
    }

    fn parse_apply(&mut self) -> Result<usize, Error> {
        let left = (self.parse_literal())?;
        if self.get_current_token() == CurrentToken::Has(Tokn::Bang) {
            self.consume_token();
            println!("its bang in apply1: {:?}", left);
            let qidx = (self.parse_aexp())?;
            println!("its bang in apply2: {:?}", self.vm.borrow().get_epiq(qidx));
            let id = self.vm.borrow_mut().alloc(Epiq::Appl(left, qidx));
            push!(self, Epiq::Eval(UNIT_INDX, id))
        } else {
            Err(Error::UnknownError(20)) // 普通は通らない
        }
    }
}
<commit_msg>prepare for LL(k), still under construction<commit_after>macro_rules! push {
    ($s:ident, $t:expr) => {{
        // println!("parser push: {:?}", $t);
        Ok($s.vm.borrow_mut().alloc($t))
    }}
}

mod error;

use std::rc::Rc;
use std::cell::RefCell;
use std::usize::MAX;
use core::*;
use lexer::*;
use self::error::Error;

const UNIT_INDX: usize = 5;

pub struct Parser<'a> {
    lexer: Lexer<'a, 'a>,
    vm: Rc<RefCell<Heliqs>>,
    // state: State,
    current_token: RefCell<CurrentToken>,
    // aexp_tokens: Vec<Vec<Tokn>>,

    lookahead: [CurrentToken; 2],
    p: usize,
}

#[derive(Eq, PartialEq, Clone, Debug)]
enum CurrentToken {
    SOT, // Start Of Tokens
    Has(Tokn),
    EOT, // End Of Tokens
}

impl<'a> Parser<'a> {
    pub fn new(lexer: Lexer<'a, 'a>, vm: Rc<RefCell<Heliqs>>) -> Self {
        let mut parser = Parser {
            lexer: lexer,
            vm: vm,
            // state: State::Aexp,
            current_token: RefCell::new(CurrentToken::SOT),
            // aexp_tokens: vec![vec![]],
            lookahead: [CurrentToken::SOT, CurrentToken::SOT],
            p: 1, // 0にはCurrentToken::SOTを入れることが固定で決まっているので、consumeを開始するのは1から
        };

        parser.consume_token();

        parser
    }

    // Unitは常に1つにする(index固定)
    fn add_unit(&mut self) {
        let _unit = self.vm.borrow_mut().alloc(Epiq::Unit);
    }

    fn add_prim(&mut self, name: &str) {
        let prim = self.vm.borrow_mut().alloc(Epiq::Prim(name.to_string()));
        self.vm.borrow_mut().define(name, prim);
    }

    pub fn parse(&mut self) {

        self.add_prim("decr");
        self.add_prim("ltoreq");
        self.add_prim("eq");
        self.add_prim("plus");
        self.add_prim("minus");

        self.add_unit();

        self.consume_token();

        let _ = self.parse_aexp();
    }

    fn get_next_token_buffer_index(&self, current: usize) -> usize {
        1 - current
    }

    fn set_current_token(&mut self, t: CurrentToken) {
        // let mut token = self.current_token.borrow_mut();
        // *token = t;

        self.lookahead[self.p] = t;
        self.p = self.get_next_token_buffer_index(self.p);
    }

    // ひどい名前
    // 指定された番目のCurrentTokenを返す
    //
    fn index_from_index(&self, i: usize) -> usize {
        // i == 0 -> self.p
        // i == 1 -> 1 - self.p
        match i {
            0 => self.p,
            1 => self.get_next_token_buffer_index(self.p),
            _ => MAX,
        }
    }

    fn get_token(&self, i: usize) -> CurrentToken {
        self.lookahead[self.index_from_index(i)].clone()
    }

    fn get_current_token(&self) -> CurrentToken {
        // self.current_token.borrow().clone()
        // self.lookahead[self.p].clone()
        self.get_token(0)
    }

    fn consume_token(&mut self) {
        let res = self.lexer.tokenize();
        match res {
            TokenizeResult::Ok(t) => self.set_current_token(CurrentToken::Has(t)),
            TokenizeResult::Err(_e) => {},
            TokenizeResult::EOF => self.set_current_token(CurrentToken::EOT),
        }
    }

    fn parse_aexp(&mut self) -> Result<usize, Error> {
        let res = self.get_current_token();

        match res {
            // 中置記法の判断をする
            CurrentToken::Has(Tokn::Chvc(_)) |
            CurrentToken::Has(Tokn::Nmbr(_))
            if self.get_token(1) == CurrentToken::Has(Tokn::Bang) => {
                self.parse_apply()
            },

            // LL(1)の範囲内
            CurrentToken::Has(Tokn::Atsm) => {
                self.consume_token();
                self.parse_resolve()
            },

            CurrentToken::Has(Tokn::Sgqt) => {
                self.consume_token();
                self.parse_otag(Tokn::Sgqt)
            },

            CurrentToken::Has(Tokn::Pipe) => {
                self.consume_token();
                self.parse_otag(Tokn::Pipe)
            },
            CurrentToken::Has(Tokn::Crrt) => {
                self.consume_token();
                self.parse_otag(Tokn::Crrt)
            },
            CurrentToken::Has(Tokn::Smcl) => {
                self.consume_token();
                Ok(UNIT_INDX)
            }
            CurrentToken::Has(Tokn::Lbkt) => {
                self.consume_token();
                self.parse_list()
            },
            CurrentToken::Has(Tokn::Dbqt) => {
                self.consume_token();
                self.parse_text()
            },

            _ => {
                self.parse_literal()
                // // 中置記法の判断をする
                // let token0 = self.get_token(0);
                // match token0 {
                //     CurrentToken::Has(Tokn::Chvc(_)) |
                //     CurrentToken::Has(Tokn::Nmbr(_))
                //     if self.get_token(1) == CurrentToken::Has(Tokn::Bang) => {
                //         self.parse_apply()
                //     }
                //     _ => self.parse_literal()
                // }
            },
        }
    }

    fn parse_resolve(&mut self) -> Result<usize, Error> {
        // let pidx = (self.parse_aexp())?;
        let qidx = (self.parse_literal())?;
        let id = self.vm.borrow_mut().alloc(Epiq::Rslv(UNIT_INDX, qidx));
        push!(self, Epiq::Eval(UNIT_INDX, id))
    }

    // Pipe QTag Pval QVal
    fn parse_otag(&mut self, tokn: Tokn) -> Result<usize, Error> {
        let current_token = self.get_current_token();
        match current_token {
            CurrentToken::Has(Tokn::Otag(ref otag)) => {
                self.consume_token();

                match tokn {
                    Tokn::Pipe => {
                        let pidx = (self.parse_aexp())?;
                        let qidx = (self.parse_aexp())?;
                        self.match_otag(pidx, qidx, otag)
                    },
                    Tokn::Crrt => {
                        match otag.as_ref() {
                            // ^Tと^Fは特別扱い
                            "T" => push!(self, Epiq::Tval),
                            "F" => push!(self, Epiq::Fval),
                            _ =>  {
                                // 現在は^Tか^Fしか認めていないが、将来のため
                                let pidx = (self.parse_aexp())?;
                                let qidx = (self.parse_aexp())?;
                                push!(self, Epiq::Mpiq{o: otag.clone(), p: pidx, q: qidx})
                            },
                        }
                    },
                    Tokn::Sgqt => {
                        // 引数は一つ、それをqとみなす
                        let qidx = (self.parse_aexp())?;
                        self.match_otag(UNIT_INDX, qidx, otag)
                    },
                    _ => Err(Error::UnknownError(255)),
                }
            },

            CurrentToken::Has(ref t) => Err(Error::TokenError(t.clone())),
            _ => Err(Error::UnknownError(1)),
        }
    }

    fn match_otag(&mut self, pidx: NodeId, qidx: NodeId, otag: &str) -> Result<usize, Error> {
        match otag {
            ">" => push!(self, Epiq::Eval(pidx, qidx)),
            ":" => push!(self, Epiq::Lpiq(pidx, qidx)),
            "!" => push!(self, Epiq::Appl(pidx, qidx)),
            "@" => push!(self, Epiq::Rslv(pidx, qidx)),
            "?" => push!(self, Epiq::Cond(pidx, qidx)),
            "%" => push!(self, Epiq::Envn(pidx, qidx)),
            "#" => push!(self, Epiq::Bind(pidx, qidx)),
            "." => push!(self, Epiq::Accs(pidx, qidx)),
            r"\" => push!(self, Epiq::Lmbd(pidx, qidx)),

            _ => {
                push!(self, Epiq::Tpiq{o: otag.to_string(), p: pidx, q: qidx})
            },
        }
    }

    fn parse_list(&mut self) -> Result<usize, Error> {
        let current_token = self.get_current_token();
        // 閉じbracketが出るまで再帰呼出
        match current_token {
            CurrentToken::Has(Tokn::Rbkt) => {
                self.consume_token();
                push!(self, Epiq::Unit)
            },
            _ => {
                let pidx = (self.parse_aexp())?;
                let qidx = (self.parse_list())?;
                push!(self, Epiq::Lpiq(pidx, qidx))
            }
        }
    }

    fn parse_text(&mut self) -> Result<usize, Error> {
        let current_token1 = self.get_current_token();
        match current_token1 {
            CurrentToken::Has(Tokn::Chvc(ref s)) => {
                self.consume_token();
                let current_token2 = self.get_current_token();
                match current_token2 {
                    CurrentToken::Has(Tokn::Dbqt) => {
                        self.consume_token();
                        push!(self, Epiq::Text(s.clone()))
                    },
                    _ => Err(Error::UnknownError(13)),
                }
            },
            _ => Err(Error::UnknownError(12)),
        }
    }

    fn parse_literal(&mut self) -> Result<usize, Error> {
        let current_token = self.get_current_token();
        match current_token {
            CurrentToken::Has(Tokn::Chvc(ref s)) => {
                self.consume_token();
                push!(self, Epiq::Name(s.clone()))
            },
            CurrentToken::Has(Tokn::Nmbr(ref s)) => {
                self.consume_token();
                push!(self, Epiq::Uit8(s.parse::<i64>().unwrap()))
            },
            _ => Err(Error::UnknownError(10)),
        }
    }

    fn parse_apply(&mut self) -> Result<usize, Error> {
        let left = (self.parse_literal())?;
        if self.get_current_token() == CurrentToken::Has(Tokn::Bang) {
            self.consume_token();
            println!("its bang in apply1: {:?}", left);
            let qidx = (self.parse_aexp())?;
            println!("its bang in apply2: {:?}", self.vm.borrow().get_epiq(qidx));
            let id = self.vm.borrow_mut().alloc(Epiq::Appl(left, qidx));
            push!(self, Epiq::Eval(UNIT_INDX, id))
        } else {
            Err(Error::UnknownError(20)) // 普通は通らない
        }
    }
}
<|endoftext|>


<commit_before>extern crate nix;

use std;
use std::fs::File;
use std::io::Read;
use time::{Time, TimeDelta};
use base::*;
use std::os::linux::fs::MetadataExt;
use std::os::unix::io::AsRawFd;
use self::nix::fcntl;

use super::input::*;

const FORMAT: SampleFormat = SampleFormat::F32LE;
const FILE_REOPEN_FREQUENCY_SECS: i64 = 2;

pub struct PipeInput {
    spec: DeviceSpec,
    sample_rate: f32,
    file: Option<File>,

    last_open_time: Time,

    period_duration: TimeDelta,

    reference_time: Time,
    pos: i64,

    leftover: Vec<u8>,
}

impl PipeInput {
    pub fn open(spec: DeviceSpec, period_duration: TimeDelta) -> Box<PipeInput> {
        let now = Time::now();
        let sample_rate = spec.sample_rate.unwrap_or(48000) as f32;
        Box::new(PipeInput {
            spec: spec,
            sample_rate: sample_rate,
            file: None,
            last_open_time: now - TimeDelta::seconds(FILE_REOPEN_FREQUENCY_SECS),
            period_duration: period_duration,
            reference_time: now,
            pos: 0,
            leftover: vec![],
        })
    }

    fn try_reopen(&mut self) {
        let now = Time::now();
        if now - self.last_open_time < TimeDelta::seconds(FILE_REOPEN_FREQUENCY_SECS) {
            return;
        }
        self.last_open_time = now;
        match File::open(&self.spec.id) {
            Err(_) => {
                self.file = None;
            }
            Ok(f) => {
                // Replace the pipe if we didn't have it before or inode has changed.
                let replace = match (self.file.as_mut().map(|f| f.metadata()), f.metadata()) {
                    (None, _) => true,
                    (Some(Ok(m1)), Ok(m2)) => m1.st_ino() != m2.st_ino(),
                    (_, Err(e)) => {
                        println!("ERROR: stat() failed: {}", e);
                        false
                    }
                    (Some(Err(e)), _) => {
                        println!("ERROR: stat() failed: {}", e);
                        false
                    }
                };
                if replace {
                    println!("INFO: Opened input: {}", self.spec.id);
                    match fcntl::fcntl(f.as_raw_fd(), fcntl::FcntlArg::F_SETPIPE_SZ(16384)) {
                        Err(e) => println!("WARNING: failed to set buffer size for pipe: {}", e),
                        _ => (),
                    }

                    match fcntl::fcntl(f.as_raw_fd(), fcntl::FcntlArg::F_SETFL(fcntl::O_NONBLOCK)) {
                        Err(e) => {
                            println!("ERROR: failed to set O_NONBLOCK: {}", e);
                            return;
                        }
                        _ => (),
                    }

                    self.file = Some(f);
                    self.leftover.clear();
                }
            }
        }
    }
}

impl Input for PipeInput {
    fn read(&mut self) -> Result<Option<Frame>> {
        self.try_reopen();

        let bytes_per_frame = FORMAT.bytes_per_sample() * self.spec.channels.len();

        let size = (self.period_duration * self.sample_rate as i64 / TimeDelta::seconds(1)
            * bytes_per_frame as i64) as usize / 2;
        let mut buffer = vec![0u8; size];

        buffer[0..self.leftover.len()].copy_from_slice(&self.leftover[..]);
        let pos = self.leftover.len();
        let bytes_read = self.leftover.len() + match self.file.as_mut().map(|f| f.read(&mut buffer[pos..])) {
            None | Some(Ok(0)) => {
                std::thread::sleep(self.period_duration.as_duration());
                return Ok(None);
            }
            Some(Ok(result)) => result,
            Some(Err(err)) => {
                println!("ERROR: read returned: {}", err);
                self.file = None;
                return Ok(None);
            }
        };

        let leftover_bytes = bytes_read % bytes_per_frame;
        let bytes_to_use = bytes_read - leftover_bytes;
        self.leftover = buffer[(buffer.len() - leftover_bytes)..].to_vec();
        if bytes_to_use == 0 {
            return Ok(None);
        }

        let mut frame = Frame::from_buffer(
            FORMAT,
            self.sample_rate as f32,
            &self.spec.channels,
            &buffer[0..bytes_to_use],
            get_sample_timestamp(self.reference_time, self.sample_rate, self.pos),
        );

        self.pos += frame.len() as i64;

        let now = Time::now();
        if now - frame.timestamp > self.period_duration * 5 {
            println!(
                "Resetting pipe input, {}",
                (now - frame.timestamp).in_milliseconds()
            );
            self.reference_time = now - self.period_duration;
            self.pos = frame.len() as i64;
            frame.timestamp = self.reference_time;
        }

        std::thread::sleep((frame.timestamp - now).as_duration());

        Ok(Some(frame))
    }

    fn min_delay(&self) -> TimeDelta {
        self.period_duration
    }
}
<commit_msg>Handle EAGAIN in pipe input<commit_after>extern crate libc;
extern crate nix;

use std;
use std::fs::File;
use std::io::Read;
use base::*;
use time::{Time, TimeDelta};
use std::os::linux::fs::MetadataExt;
use std::os::unix::io::AsRawFd;
use self::nix::fcntl;

use super::input::*;

const FORMAT: SampleFormat = SampleFormat::F32LE;
const FILE_REOPEN_FREQUENCY_SECS: i64 = 2;

pub struct PipeInput {
    spec: DeviceSpec,
    sample_rate: f32,
    file: Option<File>,

    last_open_time: Time,

    period_duration: TimeDelta,

    reference_time: Time,
    pos: i64,

    leftover: Vec<u8>,
}

impl PipeInput {
    pub fn open(spec: DeviceSpec, period_duration: TimeDelta) -> Box<PipeInput> {
        let now = Time::now();
        let sample_rate = spec.sample_rate.unwrap_or(48000) as f32;
        Box::new(PipeInput {
            spec: spec,
            sample_rate: sample_rate,
            file: None,
            last_open_time: now - TimeDelta::seconds(FILE_REOPEN_FREQUENCY_SECS),
            period_duration: period_duration,
            reference_time: now,
            pos: 0,
            leftover: vec![],
        })
    }

    fn try_reopen(&mut self) {
        let now = Time::now();
        if now - self.last_open_time < TimeDelta::seconds(FILE_REOPEN_FREQUENCY_SECS) {
            return;
        }
        self.last_open_time = now;
        match File::open(&self.spec.id) {
            Err(_) => {
                self.file = None;
            }
            Ok(f) => {
                // Replace the pipe if we didn't have it before or inode has changed.
                let replace = match (self.file.as_mut().map(|f| f.metadata()), f.metadata()) {
                    (None, _) => true,
                    (Some(Ok(m1)), Ok(m2)) => m1.st_ino() != m2.st_ino(),
                    (_, Err(e)) => {
                        println!("ERROR: stat() failed: {}", e);
                        false
                    }
                    (Some(Err(e)), _) => {
                        println!("ERROR: stat() failed: {}", e);
                        false
                    }
                };
                if replace {
                    println!("INFO: Opened input: {}", self.spec.id);
                    match fcntl::fcntl(f.as_raw_fd(), fcntl::FcntlArg::F_SETPIPE_SZ(16384)) {
                        Err(e) => println!("WARNING: failed to set buffer size for pipe: {}", e),
                        _ => (),
                    }

                    match fcntl::fcntl(f.as_raw_fd(), fcntl::FcntlArg::F_SETFL(fcntl::O_NONBLOCK)) {
                        Err(e) => {
                            println!("ERROR: failed to set O_NONBLOCK: {}", e);
                            return;
                        }
                        _ => (),
                    }

                    self.file = Some(f);
                    self.leftover.clear();
                }
            }
        }
    }
}

impl Input for PipeInput {
    fn read(&mut self) -> Result<Option<Frame>> {
        self.try_reopen();

        let bytes_per_frame = FORMAT.bytes_per_sample() * self.spec.channels.len();

        let size = (self.period_duration * self.sample_rate as i64 / TimeDelta::seconds(1)
            * bytes_per_frame as i64) as usize / 2;
        let mut buffer = vec![0u8; size];

        buffer[0..self.leftover.len()].copy_from_slice(&self.leftover[..]);
        let pos = self.leftover.len();
        let bytes_read = self.leftover.len() + match self.file.as_mut().map(|f| f.read(&mut buffer[pos..])) {
            None | Some(Ok(0)) => {
                std::thread::sleep(self.period_duration.as_duration());
                return Ok(None);
            }
            Some(Ok(result)) => result,
            Some(Err(err)) => {
                if err.raw_os_error() != Some(libc::EAGAIN) {
                    println!("ERROR: read returned: {}", err);
                    self.file = None;
                }
                return Ok(None);
            }
        };

        let leftover_bytes = bytes_read % bytes_per_frame;
        let bytes_to_use = bytes_read - leftover_bytes;
        self.leftover = buffer[(buffer.len() - leftover_bytes)..].to_vec();
        if bytes_to_use == 0 {
            return Ok(None);
        }

        let mut frame = Frame::from_buffer(
            FORMAT,
            self.sample_rate as f32,
            &self.spec.channels,
            &buffer[0..bytes_to_use],
            get_sample_timestamp(self.reference_time, self.sample_rate, self.pos),
        );

        self.pos += frame.len() as i64;

        let now = Time::now();
        if now - frame.timestamp > self.period_duration * 5 {
            println!(
                "Resetting pipe input, {}",
                (now - frame.timestamp).in_milliseconds()
            );
            self.reference_time = now - self.period_duration;
            self.pos = frame.len() as i64;
            frame.timestamp = self.reference_time;
        }

        std::thread::sleep((frame.timestamp - now).as_duration());

        Ok(Some(frame))
    }

    fn min_delay(&self) -> TimeDelta {
        self.period_duration
    }
}
<|endoftext|>


<commit_before>extern crate quickcheck;

use self::quickcheck::{Gen, Arbitrary};

use {
    Graph,
    EdgeType,
};
use graph::{
    IndexType,
};

impl<N, E, Ty, Ix> Arbitrary for Graph<N, E, Ty, Ix>
    where N: Arbitrary,
          E: Arbitrary,
          Ty: EdgeType + Send + 'static,
          Ix: IndexType + Send,
{
    fn arbitrary<G: Gen>(g: &mut G) -> Self {
        let nodes = usize::arbitrary(g);
        if nodes == 0 {
            return Graph::with_capacity(0, 0);
        }
        // use X² for edge probability (bias towards lower)
        let edge_prob = g.gen_range(0., 1.) * g.gen_range(0., 1.);
        let edges = ((nodes as f64).powi(2) * edge_prob) as usize;
        let mut gr = Graph::with_capacity(nodes, edges);
        for _ in 0..nodes {
            gr.add_node(N::arbitrary(g));
        }
        for i in gr.node_indices() {
            for j in gr.node_indices() {
                if !gr.is_directed() && i > j {
                    continue;
                }
                let p: f64 = g.gen();
                if p <= edge_prob {
                    gr.add_edge(i, j, E::arbitrary(g));
                }
            }
        }
        gr
    }
}

<commit_msg>Add doc for Arbitrary impl<commit_after>extern crate quickcheck;

use self::quickcheck::{Gen, Arbitrary};

use {
    Graph,
    EdgeType,
};
use graph::{
    IndexType,
};

/// `Arbitrary` for `Graph` creates a graph by selecting a node count
/// and a probability for each possible edge to exist.
///
/// The result will be simple graph or digraph, with possible
/// self loops, no parallel edges.
impl<N, E, Ty, Ix> Arbitrary for Graph<N, E, Ty, Ix>
    where N: Arbitrary,
          E: Arbitrary,
          Ty: EdgeType + Send + 'static,
          Ix: IndexType + Send,
{
    fn arbitrary<G: Gen>(g: &mut G) -> Self {
        let nodes = usize::arbitrary(g);
        if nodes == 0 {
            return Graph::with_capacity(0, 0);
        }
        // use X² for edge probability (bias towards lower)
        let edge_prob = g.gen_range(0., 1.) * g.gen_range(0., 1.);
        let edges = ((nodes as f64).powi(2) * edge_prob) as usize;
        let mut gr = Graph::with_capacity(nodes, edges);
        for _ in 0..nodes {
            gr.add_node(N::arbitrary(g));
        }
        for i in gr.node_indices() {
            for j in gr.node_indices() {
                if !gr.is_directed() && i > j {
                    continue;
                }
                let p: f64 = g.gen();
                if p <= edge_prob {
                    gr.add_edge(i, j, E::arbitrary(g));
                }
            }
        }
        gr
    }
}

<|endoftext|>


<commit_before>//! Rate Limit interface
use serde::Deserialize;
use crate::{Future, Github};

pub struct RateLimit {
    github: Github,
}

impl RateLimit {
    #[doc(hidden)]
    pub fn new(github: Github) -> Self {
        Self { github }
    }

    /// https://developer.github.com/v3/rate_limit/#get-your-current-rate-limit-status
    pub fn get(&self) -> Future<RateLimitStatus> {
        self.github.get("/rate_limit")
    }
}

// representations

#[derive(Debug, Deserialize)]
pub struct RateLimitStatus {
    pub resources: RateLimitResourcesStatus,
}

#[derive(Debug, Deserialize)]
pub struct RateLimitResourcesStatus {
    pub core: RateLimitResourceStatus,
    pub search: RateLimitResourceStatus,
    pub graphql: RateLimitResourceStatus,
}

#[derive(Debug, Deserialize)]
pub struct RateLimitResourceStatus {
    pub limit: u32,
    pub remaining: u32,
    pub reset: u32, // ideally something like std::time::Duration
}
<commit_msg>capture rustfmt miss<commit_after>//! Rate Limit interface
use crate::{Future, Github};
use serde::Deserialize;

pub struct RateLimit {
    github: Github,
}

impl RateLimit {
    #[doc(hidden)]
    pub fn new(github: Github) -> Self {
        Self { github }
    }

    /// https://developer.github.com/v3/rate_limit/#get-your-current-rate-limit-status
    pub fn get(&self) -> Future<RateLimitStatus> {
        self.github.get("/rate_limit")
    }
}

// representations

#[derive(Debug, Deserialize)]
pub struct RateLimitStatus {
    pub resources: RateLimitResourcesStatus,
}

#[derive(Debug, Deserialize)]
pub struct RateLimitResourcesStatus {
    pub core: RateLimitResourceStatus,
    pub search: RateLimitResourceStatus,
    pub graphql: RateLimitResourceStatus,
}

#[derive(Debug, Deserialize)]
pub struct RateLimitResourceStatus {
    pub limit: u32,
    pub remaining: u32,
    pub reset: u32, // ideally something like std::time::Duration
}
<|endoftext|>


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

use super::*;

use cocoa::foundation::NSUInteger;

#[repr(u64)]
#[derive(Clone, Debug)]
pub enum MTLLoadAction {
    DontCare = 0,
    Load = 1,
    Clear = 2,
}

#[repr(u64)]
#[derive(Clone, Debug)]
pub enum MTLStoreAction {
    DontCare = 0,
    Store = 1,
    MultisampleResolve = 2,
    StoreAndMultisampleResolve = 3,
    Unknown = 4,
    CustomSampleDepthStore = 5,
}

#[repr(C)]
#[derive(Clone, Debug)]
pub struct MTLClearColor {
    red: f64,
    green: f64,
    blue: f64,
    alpha: f64
}

impl MTLClearColor {
    #[inline]
    pub fn new(red: f64, green: f64, blue: f64, alpha: f64) -> Self {
        MTLClearColor {
            red: red,
            green: green,
            blue: blue,
            alpha: alpha
        }
    }
}

pub enum MTLRenderPassAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassAttachmentDescriptor;
    pub struct RenderPassAttachmentDescriptor;
    pub struct RenderPassAttachmentDescriptorRef;
}

impl RenderPassAttachmentDescriptorRef {
    pub fn texture(&self) -> Option<&TextureRef> {
        unsafe {
            msg_send![self, texture]
        }
    }

    pub fn set_texture(&self, texture: Option<&TextureRef>) {
        unsafe {
            msg_send![self, setTexture:texture];
        }
    }

    pub fn level(&self) -> NSUInteger {
        unsafe {
            msg_send![self, level]
        }
    }

    pub fn set_level(&self, level: NSUInteger) {
        unsafe {
            msg_send![self, setLevel:level]
        }
    }

    pub fn slice(&self) -> NSUInteger {
        unsafe {
            msg_send![self, slice]
        }
    }

    pub fn set_slice(&self, slice: NSUInteger) {
        unsafe {
            msg_send![self, setSlice:slice]
        }
    }

    pub fn depth_plane(&self) -> NSUInteger {
        unsafe {
            msg_send![self, depthPlane]
        }
    }

    pub fn set_depth_plane(&self, depth_plane: NSUInteger) {
        unsafe {
            msg_send![self, setDepthPlane:depth_plane]
        }
    }

    pub fn resolve_texture(&self) -> Option<&TextureRef> {
        unsafe {
            msg_send![self, resolveTexture]
        }
    }

    pub fn set_resolve_texture(&self, resolve_texture: Option<&TextureRef>) {
        unsafe {
            msg_send![self, setResolveTexture:resolve_texture]
        }
    }

    pub fn resolve_level(&self) -> NSUInteger {
        unsafe {
            msg_send![self, resolveLevel]
        }
    }

    pub fn set_resolve_level(&self, resolve_level: NSUInteger) {
        unsafe {
            msg_send![self, setResolveLevel:resolve_level]
        }
    }

    pub fn resolve_slice(&self) -> NSUInteger {
        unsafe {
            msg_send![self, resolveSlice]
        }
    }

    pub fn set_resolve_slice(&self, resolve_slice: NSUInteger) {
        unsafe {
            msg_send![self, setResolveSlice:resolve_slice]
        }
    }

    pub fn resolve_depth_plane(&self) -> NSUInteger {
        unsafe {
            msg_send![self, resolveDepthPlane]
        }
    }

    pub fn set_resolve_depth_plane(&self, resolve_depth_plane: NSUInteger) {
        unsafe {
            msg_send![self, setResolveDepthPlane:resolve_depth_plane]
        }
    }

    pub fn load_action(&self) -> MTLLoadAction {
        unsafe {
            msg_send![self, loadAction]
        }
    }

    pub fn set_load_action(&self, load_action: MTLLoadAction) {
        unsafe {
            msg_send![self, setLoadAction:load_action]
        }
    }

    pub fn store_action(&self) -> MTLStoreAction {
        unsafe {
            msg_send![self, storeAction]
        }
    }

    pub fn set_store_action(&self, store_action: MTLStoreAction) {
        unsafe {
            msg_send![self, setStoreAction:store_action]
        }
    }
}

pub enum MTLRenderPassColorAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassColorAttachmentDescriptor;
    pub struct RenderPassColorAttachmentDescriptor;
    pub struct RenderPassColorAttachmentDescriptorRef;
    type ParentType = RenderPassAttachmentDescriptorRef;
}

impl RenderPassColorAttachmentDescriptor {
    pub fn new() -> Self {
        unsafe {
            let class = class!(MTLRenderPassColorAttachmentDescriptor);
            msg_send![class, new]
        }
    }
}

impl RenderPassColorAttachmentDescriptorRef {
    pub fn clear_color(&self) -> MTLClearColor {
        unsafe {
            msg_send![self, clearColor]
        }
    }

    pub fn set_clear_color(&self, clear_color: MTLClearColor) {
        unsafe {
            msg_send![self, setClearColor:clear_color]
        }
    }
}

pub enum MTLRenderPassDepthAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassDepthAttachmentDescriptor;
    pub struct RenderPassDepthAttachmentDescriptor;
    pub struct RenderPassDepthAttachmentDescriptorRef;
    type ParentType = RenderPassAttachmentDescriptorRef;
}

impl RenderPassDepthAttachmentDescriptorRef {
    pub fn clear_depth(&self) -> f64 {
        unsafe {
            msg_send![self, clearDepth]
        }
    }

    pub fn set_clear_depth(&self, clear_depth: f64) {
        unsafe {
            msg_send![self, setClearDepth:clear_depth]
        }
    }
}

pub enum MTLRenderPassStencilAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassStencilAttachmentDescriptor;
    pub struct RenderPassStencilAttachmentDescriptor;
    pub struct RenderPassStencilAttachmentDescriptorRef;
    type ParentType = RenderPassAttachmentDescriptorRef;
}

impl RenderPassStencilAttachmentDescriptorRef {
    pub fn clear_stencil(&self) -> u32 {
        unsafe {
            msg_send![self, clearStencil]
        }
    }

    pub fn set_clear_stencil(&self, clear_stencil: u32) {
        unsafe {
            msg_send![self, setClearStencil:clear_stencil]
        }
    }
}

pub enum MTLRenderPassColorAttachmentDescriptorArray {}

foreign_obj_type! {
    type CType = MTLRenderPassColorAttachmentDescriptorArray;
    pub struct RenderPassColorAttachmentDescriptorArray;
    pub struct RenderPassColorAttachmentDescriptorArrayRef;
}

impl RenderPassColorAttachmentDescriptorArrayRef {
    pub fn object_at(&self, index: usize) -> Option<&RenderPassColorAttachmentDescriptorRef> {
        unsafe {
            msg_send![self, objectAtIndexedSubscript:index]
        }
    }

    pub fn set_object_at(&self, index: usize, attachment: Option<&RenderPassColorAttachmentDescriptorRef>) {
        unsafe {
            msg_send![self, setObject:attachment
                     atIndexedSubscript:index]
        }
    }
}

pub enum MTLRenderPassDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassDescriptor;
    pub struct RenderPassDescriptor;
    pub struct RenderPassDescriptorRef;
}

impl RenderPassDescriptor {
    pub fn new<'a>() -> &'a RenderPassDescriptorRef {
        unsafe {
            let class = class!(MTLRenderPassDescriptorInternal);
            msg_send![class, renderPassDescriptor]
        }
    }
}

impl RenderPassDescriptorRef {
    pub fn color_attachments(&self) -> &RenderPassColorAttachmentDescriptorArrayRef {
        unsafe {
            msg_send![self, colorAttachments]
        }
    }

    pub fn depth_attachment(&self) -> Option<&RenderPassDepthAttachmentDescriptorRef> {
        unsafe {
            msg_send![self, depthAttachment]
        }
    }

    pub fn set_depth_attachment(&self, depth_attachment: Option<&RenderPassDepthAttachmentDescriptorRef>) {
        unsafe {
            msg_send![self, setDepthAttachment:depth_attachment]
        }
    }

    pub fn stencil_attachment(&self) -> Option<&RenderPassStencilAttachmentDescriptorRef> {
        unsafe {
            msg_send![self, stencilAttachment]
        }
    }

    pub fn set_stencil_attachment(&self, stencil_attachment: Option<&RenderPassStencilAttachmentDescriptorRef>) {
        unsafe {
            msg_send![self, setStencilAttachment:stencil_attachment]
        }
    }

    pub fn visibility_result_buffer(&self) -> Option<&BufferRef> {
        unsafe {
            msg_send![self, visibilityResultBuffer]
        }
    }

    pub fn set_visibility_result_buffer(&self, buffer: Option<&BufferRef>) {
        unsafe {
            msg_send![self, setVisibilityResultBuffer:buffer]
        }
    }

    pub fn render_target_array_length(&self) -> NSUInteger {
        unsafe {
            msg_send![self, renderTargetArrayLength]
        }
    }

    pub fn set_render_target_array_length(&self, length: NSUInteger) {
        unsafe {
            msg_send![self, setRenderTargetArrayLength:length]
        }
    }
}
<commit_msg>follow field initialization shorthand (RFC 1682)<commit_after>// Copyright 2016 GFX developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use super::*;

use cocoa::foundation::NSUInteger;

#[repr(u64)]
#[derive(Clone, Debug)]
pub enum MTLLoadAction {
    DontCare = 0,
    Load = 1,
    Clear = 2,
}

#[repr(u64)]
#[derive(Clone, Debug)]
pub enum MTLStoreAction {
    DontCare = 0,
    Store = 1,
    MultisampleResolve = 2,
    StoreAndMultisampleResolve = 3,
    Unknown = 4,
    CustomSampleDepthStore = 5,
}

#[repr(C)]
#[derive(Clone, Debug)]
pub struct MTLClearColor {
    red: f64,
    green: f64,
    blue: f64,
    alpha: f64
}

impl MTLClearColor {
    #[inline]
    pub fn new(red: f64, green: f64, blue: f64, alpha: f64) -> Self {
        MTLClearColor {
            red,
            green,
            blue,
            alpha
        }
    }
}

pub enum MTLRenderPassAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassAttachmentDescriptor;
    pub struct RenderPassAttachmentDescriptor;
    pub struct RenderPassAttachmentDescriptorRef;
}

impl RenderPassAttachmentDescriptorRef {
    pub fn texture(&self) -> Option<&TextureRef> {
        unsafe {
            msg_send![self, texture]
        }
    }

    pub fn set_texture(&self, texture: Option<&TextureRef>) {
        unsafe {
            msg_send![self, setTexture:texture];
        }
    }

    pub fn level(&self) -> NSUInteger {
        unsafe {
            msg_send![self, level]
        }
    }

    pub fn set_level(&self, level: NSUInteger) {
        unsafe {
            msg_send![self, setLevel:level]
        }
    }

    pub fn slice(&self) -> NSUInteger {
        unsafe {
            msg_send![self, slice]
        }
    }

    pub fn set_slice(&self, slice: NSUInteger) {
        unsafe {
            msg_send![self, setSlice:slice]
        }
    }

    pub fn depth_plane(&self) -> NSUInteger {
        unsafe {
            msg_send![self, depthPlane]
        }
    }

    pub fn set_depth_plane(&self, depth_plane: NSUInteger) {
        unsafe {
            msg_send![self, setDepthPlane:depth_plane]
        }
    }

    pub fn resolve_texture(&self) -> Option<&TextureRef> {
        unsafe {
            msg_send![self, resolveTexture]
        }
    }

    pub fn set_resolve_texture(&self, resolve_texture: Option<&TextureRef>) {
        unsafe {
            msg_send![self, setResolveTexture:resolve_texture]
        }
    }

    pub fn resolve_level(&self) -> NSUInteger {
        unsafe {
            msg_send![self, resolveLevel]
        }
    }

    pub fn set_resolve_level(&self, resolve_level: NSUInteger) {
        unsafe {
            msg_send![self, setResolveLevel:resolve_level]
        }
    }

    pub fn resolve_slice(&self) -> NSUInteger {
        unsafe {
            msg_send![self, resolveSlice]
        }
    }

    pub fn set_resolve_slice(&self, resolve_slice: NSUInteger) {
        unsafe {
            msg_send![self, setResolveSlice:resolve_slice]
        }
    }

    pub fn resolve_depth_plane(&self) -> NSUInteger {
        unsafe {
            msg_send![self, resolveDepthPlane]
        }
    }

    pub fn set_resolve_depth_plane(&self, resolve_depth_plane: NSUInteger) {
        unsafe {
            msg_send![self, setResolveDepthPlane:resolve_depth_plane]
        }
    }

    pub fn load_action(&self) -> MTLLoadAction {
        unsafe {
            msg_send![self, loadAction]
        }
    }

    pub fn set_load_action(&self, load_action: MTLLoadAction) {
        unsafe {
            msg_send![self, setLoadAction:load_action]
        }
    }

    pub fn store_action(&self) -> MTLStoreAction {
        unsafe {
            msg_send![self, storeAction]
        }
    }

    pub fn set_store_action(&self, store_action: MTLStoreAction) {
        unsafe {
            msg_send![self, setStoreAction:store_action]
        }
    }
}

pub enum MTLRenderPassColorAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassColorAttachmentDescriptor;
    pub struct RenderPassColorAttachmentDescriptor;
    pub struct RenderPassColorAttachmentDescriptorRef;
    type ParentType = RenderPassAttachmentDescriptorRef;
}

impl RenderPassColorAttachmentDescriptor {
    pub fn new() -> Self {
        unsafe {
            let class = class!(MTLRenderPassColorAttachmentDescriptor);
            msg_send![class, new]
        }
    }
}

impl RenderPassColorAttachmentDescriptorRef {
    pub fn clear_color(&self) -> MTLClearColor {
        unsafe {
            msg_send![self, clearColor]
        }
    }

    pub fn set_clear_color(&self, clear_color: MTLClearColor) {
        unsafe {
            msg_send![self, setClearColor:clear_color]
        }
    }
}

pub enum MTLRenderPassDepthAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassDepthAttachmentDescriptor;
    pub struct RenderPassDepthAttachmentDescriptor;
    pub struct RenderPassDepthAttachmentDescriptorRef;
    type ParentType = RenderPassAttachmentDescriptorRef;
}

impl RenderPassDepthAttachmentDescriptorRef {
    pub fn clear_depth(&self) -> f64 {
        unsafe {
            msg_send![self, clearDepth]
        }
    }

    pub fn set_clear_depth(&self, clear_depth: f64) {
        unsafe {
            msg_send![self, setClearDepth:clear_depth]
        }
    }
}

pub enum MTLRenderPassStencilAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassStencilAttachmentDescriptor;
    pub struct RenderPassStencilAttachmentDescriptor;
    pub struct RenderPassStencilAttachmentDescriptorRef;
    type ParentType = RenderPassAttachmentDescriptorRef;
}

impl RenderPassStencilAttachmentDescriptorRef {
    pub fn clear_stencil(&self) -> u32 {
        unsafe {
            msg_send![self, clearStencil]
        }
    }

    pub fn set_clear_stencil(&self, clear_stencil: u32) {
        unsafe {
            msg_send![self, setClearStencil:clear_stencil]
        }
    }
}

pub enum MTLRenderPassColorAttachmentDescriptorArray {}

foreign_obj_type! {
    type CType = MTLRenderPassColorAttachmentDescriptorArray;
    pub struct RenderPassColorAttachmentDescriptorArray;
    pub struct RenderPassColorAttachmentDescriptorArrayRef;
}

impl RenderPassColorAttachmentDescriptorArrayRef {
    pub fn object_at(&self, index: usize) -> Option<&RenderPassColorAttachmentDescriptorRef> {
        unsafe {
            msg_send![self, objectAtIndexedSubscript:index]
        }
    }

    pub fn set_object_at(&self, index: usize, attachment: Option<&RenderPassColorAttachmentDescriptorRef>) {
        unsafe {
            msg_send![self, setObject:attachment
                     atIndexedSubscript:index]
        }
    }
}

pub enum MTLRenderPassDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassDescriptor;
    pub struct RenderPassDescriptor;
    pub struct RenderPassDescriptorRef;
}

impl RenderPassDescriptor {
    pub fn new<'a>() -> &'a RenderPassDescriptorRef {
        unsafe {
            let class = class!(MTLRenderPassDescriptorInternal);
            msg_send![class, renderPassDescriptor]
        }
    }
}

impl RenderPassDescriptorRef {
    pub fn color_attachments(&self) -> &RenderPassColorAttachmentDescriptorArrayRef {
        unsafe {
            msg_send![self, colorAttachments]
        }
    }

    pub fn depth_attachment(&self) -> Option<&RenderPassDepthAttachmentDescriptorRef> {
        unsafe {
            msg_send![self, depthAttachment]
        }
    }

    pub fn set_depth_attachment(&self, depth_attachment: Option<&RenderPassDepthAttachmentDescriptorRef>) {
        unsafe {
            msg_send![self, setDepthAttachment:depth_attachment]
        }
    }

    pub fn stencil_attachment(&self) -> Option<&RenderPassStencilAttachmentDescriptorRef> {
        unsafe {
            msg_send![self, stencilAttachment]
        }
    }

    pub fn set_stencil_attachment(&self, stencil_attachment: Option<&RenderPassStencilAttachmentDescriptorRef>) {
        unsafe {
            msg_send![self, setStencilAttachment:stencil_attachment]
        }
    }

    pub fn visibility_result_buffer(&self) -> Option<&BufferRef> {
        unsafe {
            msg_send![self, visibilityResultBuffer]
        }
    }

    pub fn set_visibility_result_buffer(&self, buffer: Option<&BufferRef>) {
        unsafe {
            msg_send![self, setVisibilityResultBuffer:buffer]
        }
    }

    pub fn render_target_array_length(&self) -> NSUInteger {
        unsafe {
            msg_send![self, renderTargetArrayLength]
        }
    }

    pub fn set_render_target_array_length(&self, length: NSUInteger) {
        unsafe {
            msg_send![self, setRenderTargetArrayLength:length]
        }
    }
}
<|endoftext|>