<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::data_provider::DataProvider;
use crate::errors::*;
use crate::geometry::{Aabb, Cube, Frustum};
use crate::iterator::{PointCloud, PointLocation};
use crate::math::base::{HasAabbIntersector, IntersectAabb};
use crate::math::sat::{ConvexPolyhedron, Relation};
use crate::math::AllPoints;
use crate::proto;
use crate::read_write::{Encoding, NodeIterator, PositionEncoding};
use crate::{AttributeDataType, PointCloudMeta, CURRENT_VERSION};
use fnv::FnvHashMap;
use nalgebra::{Matrix4, Point3};
use num::clamp;
use std::cmp::Ordering;
use std::collections::{BinaryHeap, HashMap};
use std::io::{BufReader, Read};

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

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

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

#[cfg(test)]
mod tests;

#[derive(Clone, Debug)]
pub struct OctreeMeta {
    pub resolution: f64,
    pub bounding_box: Aabb,
    attribute_data_types: HashMap<String, AttributeDataType>,
}

impl PointCloudMeta for OctreeMeta {
    fn attribute_data_types(&self) -> &HashMap<String, AttributeDataType> {
        &self.attribute_data_types
    }
}

impl OctreeMeta {
    /// An octree currently does not store its data types, instead, color and
    /// intensity are implied. We already do have attributes as part of the
    /// meta data structure, but not its serialized form. So the data structure
    /// is initialized with color and intensity hardcoded until attributes are
    /// in the meta proto.
    pub fn new_with_standard_attributes(resolution: f64, bounding_box: Aabb) -> Self {
        let attribute_data_types = vec![
            ("color".to_string(), AttributeDataType::U8Vec3),
            ("intensity".to_string(), AttributeDataType::F32),
        ]
        .into_iter()
        .collect();
        Self {
            resolution,
            bounding_box,
            attribute_data_types,
        }
    }

    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(),
            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.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_bounding_box(proto::AxisAlignedCuboid::from(&octree_meta.bounding_box));
    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 * p.to_homogeneous();
    Point3::from_homogeneous(q).unwrap()
}

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 = Aabb::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.grow(clip_point_to_hemicube(&project(matrix, p)));
    }
    let diag = rv.diag();
    diag.x * diag.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>,
}

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()?;
        if meta_proto.version < CURRENT_VERSION {
            eprintln!(
                "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, meta, nodes_proto) = match meta_proto.version {
            9 | 10 | 11 => {
                let bounding_box = Aabb::from(meta_proto.get_bounding_box());
                (
                    bounding_box.clone(),
                    OctreeMeta::new_with_standard_attributes(
                        meta_proto.deprecated_resolution,
                        bounding_box,
                    ),
                    meta_proto.get_deprecated_nodes(),
                )
            }
            12 | 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 = Aabb::from(if meta_proto.version == 12 {
                    octree_meta.get_deprecated_bounding_box()
                } else {
                    meta_proto.get_bounding_box()
                });
                (
                    bounding_box.clone(),
                    OctreeMeta::new_with_standard_attributes(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 =
            Frustum::from_matrix4(*projection_matrix).expect("Invalid projection matrix.");
        let frustum_isec = frustum.intersector().cache_separating_axes_for_aabb();
        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_isec
                            .intersect(&child.bounding_cube.to_aabb().compute_corners());
                        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(),
        })
    }

    fn nodes_in_location_impl<'a, T: HasAabbIntersector<'a>>(
        &self,
        location: &'a T,
    ) -> Vec<NodeId> {
        // TODO(nnmm): Once intersection tests use Relation, this function can traverse the octree
        // with the same strategy as get_visible_nodes(), skipping over fully-included nodes. Then
        // it's a generalized version of get_visible_nodes(), and get_visible_nodes() can use this
        // function instead.
        let isec = location.aabb_intersector();
        NodeIdsIterator::new(&self, |node_id, octree| {
            let aabb = octree.nodes[&node_id].bounding_cube.to_aabb();
            isec.intersect_aabb(&aabb)
        })
        .collect()
    }
}

impl PointCloud for Octree {
    type Id = NodeId;

    fn nodes_in_location(&self, location: &PointLocation) -> Vec<Self::Id> {
        dispatch_point_location!(Octree::nodes_in_location_impl, location, &self)
    }

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

    fn points_in_node(
        &self,
        attributes: &[&str],
        node_id: Self::Id,
        batch_size: usize,
    ) -> Result<NodeIterator> {
        let node_iterator = NodeIterator::from_data_provider(
            &*self.data_provider,
            &self.meta.attribute_data_types_for(&attributes)?,
            self.meta.encoding_for_node(node_id),
            &node_id,
            self.nodes[&node_id].num_points as usize,
            batch_size,
        )?;
        Ok(node_iterator)
    }

    /// return the bounding box saved in meta
    fn bounding_box(&self) -> &Aabb {
        &self.meta.bounding_box
    }
}

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,
        });
    }
}
<commit_msg>Please clippy nightly. (#468)<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::data_provider::DataProvider;
use crate::errors::*;
use crate::geometry::{Aabb, Cube, Frustum};
use crate::iterator::{PointCloud, PointLocation};
use crate::math::base::{HasAabbIntersector, IntersectAabb};
use crate::math::sat::{ConvexPolyhedron, Relation};
use crate::math::AllPoints;
use crate::proto;
use crate::read_write::{Encoding, NodeIterator, PositionEncoding};
use crate::{AttributeDataType, PointCloudMeta, CURRENT_VERSION};
use fnv::FnvHashMap;
use nalgebra::{Matrix4, Point3};
use num::clamp;
use std::cmp::Ordering;
use std::collections::{BinaryHeap, HashMap};
use std::io::{BufReader, Read};

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

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

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

#[cfg(test)]
mod tests;

#[derive(Clone, Debug)]
pub struct OctreeMeta {
    pub resolution: f64,
    pub bounding_box: Aabb,
    attribute_data_types: HashMap<String, AttributeDataType>,
}

impl PointCloudMeta for OctreeMeta {
    fn attribute_data_types(&self) -> &HashMap<String, AttributeDataType> {
        &self.attribute_data_types
    }
}

impl OctreeMeta {
    /// An octree currently does not store its data types, instead, color and
    /// intensity are implied. We already do have attributes as part of the
    /// meta data structure, but not its serialized form. So the data structure
    /// is initialized with color and intensity hardcoded until attributes are
    /// in the meta proto.
    pub fn new_with_standard_attributes(resolution: f64, bounding_box: Aabb) -> Self {
        let attribute_data_types = vec![
            ("color".to_string(), AttributeDataType::U8Vec3),
            ("intensity".to_string(), AttributeDataType::F32),
        ]
        .into_iter()
        .collect();
        Self {
            resolution,
            bounding_box,
            attribute_data_types,
        }
    }

    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(),
            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.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_bounding_box(proto::AxisAlignedCuboid::from(&octree_meta.bounding_box));
    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 * p.to_homogeneous();
    Point3::from_homogeneous(q).unwrap()
}

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 = Aabb::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.grow(clip_point_to_hemicube(&project(matrix, p)));
    }
    let diag = rv.diag();
    diag.x * diag.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>,
}

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()?;
        if meta_proto.version < CURRENT_VERSION {
            eprintln!(
                "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, meta, nodes_proto) = match meta_proto.version {
            9 | 10 | 11 => {
                let bounding_box = Aabb::from(meta_proto.get_bounding_box());
                (
                    bounding_box.clone(),
                    OctreeMeta::new_with_standard_attributes(
                        meta_proto.deprecated_resolution,
                        bounding_box,
                    ),
                    meta_proto.get_deprecated_nodes(),
                )
            }
            12 | 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 = Aabb::from(if meta_proto.version == 12 {
                    octree_meta.get_deprecated_bounding_box()
                } else {
                    meta_proto.get_bounding_box()
                });
                (
                    bounding_box.clone(),
                    OctreeMeta::new_with_standard_attributes(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 =
            Frustum::from_matrix4(*projection_matrix).expect("Invalid projection matrix.");
        let frustum_isec = frustum.intersector().cache_separating_axes_for_aabb();
        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_isec
                            .intersect(&child.bounding_cube.to_aabb().compute_corners());
                        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(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(),
        })
    }

    fn nodes_in_location_impl<'a, T: HasAabbIntersector<'a>>(
        &self,
        location: &'a T,
    ) -> Vec<NodeId> {
        // TODO(nnmm): Once intersection tests use Relation, this function can traverse the octree
        // with the same strategy as get_visible_nodes(), skipping over fully-included nodes. Then
        // it's a generalized version of get_visible_nodes(), and get_visible_nodes() can use this
        // function instead.
        let isec = location.aabb_intersector();
        NodeIdsIterator::new(&self, |node_id, octree| {
            let aabb = octree.nodes[&node_id].bounding_cube.to_aabb();
            isec.intersect_aabb(&aabb)
        })
        .collect()
    }
}

impl PointCloud for Octree {
    type Id = NodeId;

    fn nodes_in_location(&self, location: &PointLocation) -> Vec<Self::Id> {
        dispatch_point_location!(Octree::nodes_in_location_impl, location, &self)
    }

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

    fn points_in_node(
        &self,
        attributes: &[&str],
        node_id: Self::Id,
        batch_size: usize,
    ) -> Result<NodeIterator> {
        let node_iterator = NodeIterator::from_data_provider(
            &*self.data_provider,
            &self.meta.attribute_data_types_for(&attributes)?,
            self.meta.encoding_for_node(node_id),
            &node_id,
            self.nodes[&node_id].num_points as usize,
            batch_size,
        )?;
        Ok(node_iterator)
    }

    /// return the bounding box saved in meta
    fn bounding_box(&self) -> &Aabb {
        &self.meta.bounding_box
    }
}

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,
        });
    }
}
<|endoftext|>


<commit_before>use llvm_sys::prelude::*;
use llvm_sys::core::*;

use libc::{c_int, c_uint};

use std::marker::PhantomData;

use id::IdRef;
use opaque::Opaque;

use llvm::value::Value;
use llvm::context::Context;

pub struct Type<'cid, SubType> {
    _context_id: IdRef<'cid>,
    _marker: PhantomData<SubType>,
    _opaque: Opaque
}

impl<'cid> Type<'cid, AnyType> {
    pub fn f32<'ctx>(context: &'ctx Context<'cid>) -> &'ctx Type<'cid, AnyType> {
        unsafe {
            &*(LLVMFloatTypeInContext(context.as_raw()) as *mut Type<AnyType>)
        }
    }

    pub fn f64<'ctx>(context: &'ctx Context<'cid>) -> &'ctx Type<'cid, AnyType> {
        unsafe {
            &*(LLVMDoubleTypeInContext(context.as_raw()) as *mut Type<AnyType>)
        }
    }

    pub fn i1<'ctx>(context: &'ctx Context<'cid>) -> &'ctx Type<'cid, AnyType> {
        unsafe {
            &*(LLVMInt1TypeInContext(context.as_raw()) as *mut Type<AnyType>)
        }
    }

    pub fn i8<'ctx>(context: &'ctx Context<'cid>) -> &'ctx Type<'cid, AnyType> {
        unsafe {
            &*(LLVMInt8TypeInContext(context.as_raw()) as *mut Type<AnyType>)
        }
    }

    pub fn i16<'ctx>(context: &'ctx Context<'cid>) -> &'ctx Type<'cid, AnyType> {
        unsafe {
            &*(LLVMInt16TypeInContext(context.as_raw()) as *mut Type<AnyType>)
        }
    }

    pub fn i32<'ctx>(context: &'ctx Context<'cid>) -> &'ctx Type<'cid, AnyType> {
        unsafe {
            &*(LLVMInt32TypeInContext(context.as_raw()) as *mut Type<AnyType>)
        }
    }

    pub fn i64<'ctx>(context: &'ctx Context<'cid>) -> &'ctx Type<'cid, AnyType> {
        unsafe {
            &*(LLVMInt64TypeInContext(context.as_raw()) as *mut Type<AnyType>)
        }
    }

    pub fn void<'ctx>(context: &'ctx Context<'cid>) -> &'ctx Type<'cid, AnyType> {
        unsafe {
            &*(LLVMVoidTypeInContext(context.as_raw()) as *mut Type<AnyType>)
        }
    }

    pub fn of_value<'a, 'mid, 'fid>(value: &'a Value<'cid, 'mid, 'fid>) -> &'a Type<'cid, AnyType> {
        unsafe {
            &*(LLVMTypeOf(value.as_raw()) as *mut Type<AnyType>)
        }
    }
}

impl<'cid, SubType> Type<'cid, SubType> {
    pub fn pointer<'ctx>(inner: &'ctx Type<'cid, SubType>, address_space: c_uint) -> &'ctx Type<'cid, PointerType<SubType>> {
        unsafe {
            &*(LLVMPointerType(inner.as_raw(), address_space) as *mut Type<PointerType<SubType>>)
        }
    }

    pub fn array<'ctx>(inner: &'ctx Type<'cid, SubType>, count: c_uint) -> &'ctx Type<'cid, ArrayType<SubType>> {
        unsafe {
            &*(LLVMArrayType(inner.as_raw(), count) as *mut Type<ArrayType<SubType>>)
        }
    }

    pub fn function<'ctx, ArgTy>(params: &[&'ctx Type<'cid, ArgTy>], ret: &'ctx Type<'cid, SubType>, var_arg: bool) -> &'ctx Type<'cid, FunctionType> {
        unsafe {
            &*(LLVMFunctionType(ret.as_raw(), params.as_ptr() as *mut LLVMTypeRef, params.len() as u32, var_arg as c_int) as *mut Type<FunctionType>)
        }
    }

    pub fn upcast<TargetTy>(&self) -> &Type<'cid, TargetTy> where SubType: Upcast<TargetTy> {
        unsafe {
            &*(self.as_raw() as *mut Type<TargetTy>)
        }
    }

    pub unsafe fn cast_unchecked<TargetTy>(&self) -> &Type<'cid, TargetTy> {
        &*(self.as_raw() as *mut Type<TargetTy>)
    }

    pub fn dump(&self) {
        unsafe {
            LLVMDumpType(self.as_raw())
        }
    }

    pub fn as_raw(&self) -> LLVMTypeRef {
        self as *const Type<SubType> as *mut Type<SubType> as LLVMTypeRef
    }
}

impl<'cid> Type<'cid, FunctionType> {
    pub fn is_var_arg(&self) -> bool {
        unsafe {
            LLVMIsFunctionVarArg(self.as_raw()) != 0
        }
    }
}

impl<'cid, PointeeTy> Type<'cid, PointerType<PointeeTy>> {
    pub fn pointee_ty(&self) -> &Type<'cid, PointeeTy> {
        unsafe {
            &*(LLVMGetElementType(self.as_raw()) as *mut Type<PointeeTy>)
        }
    }
}

impl<'cid, ElementTy> Type<'cid, ArrayType<ElementTy>> {
    pub fn element_ty(&self) -> &Type<'cid, ElementTy> {
        unsafe {
            &*(LLVMGetElementType(self.as_raw()) as *mut Type<ElementTy>)
        }
    }
}

// TODO: Consider blanket impls?
pub unsafe trait Upcast<Target> { }
unsafe impl Upcast<AnyType> for AnyType { }
unsafe impl<PointeeTy> Upcast<AnyType> for PointerType<PointeeTy> { }
unsafe impl<GeneralPointeeTy, PointeeTy: Upcast<GeneralPointeeTy>> Upcast<PointerType<GeneralPointeeTy>> for PointerType<PointeeTy> { }
unsafe impl<ElementTy> Upcast<AnyType> for ArrayType<ElementTy> { }
unsafe impl<GeneralElementTy, ElementTy: Upcast<GeneralElementTy>> Upcast<ArrayType<GeneralElementTy>> for ArrayType<ElementTy> { }
unsafe impl Upcast<AnyType> for FunctionType { }

pub enum AnyType { }
pub struct PointerType<PointeeTy> {
    _marker: PhantomData<PointeeTy>
}
pub struct ArrayType<ElementTy> {
    _marker: PhantomData<ElementTy>
}
pub enum FunctionType { }
<commit_msg>Use a blanket impl to slightly simplify Upcast<commit_after>use llvm_sys::prelude::*;
use llvm_sys::core::*;

use libc::{c_int, c_uint};

use std::marker::PhantomData;

use id::IdRef;
use opaque::Opaque;

use llvm::value::Value;
use llvm::context::Context;

pub struct Type<'cid, SubType> {
    _context_id: IdRef<'cid>,
    _marker: PhantomData<SubType>,
    _opaque: Opaque
}

impl<'cid> Type<'cid, AnyType> {
    pub fn f32<'ctx>(context: &'ctx Context<'cid>) -> &'ctx Type<'cid, AnyType> {
        unsafe {
            &*(LLVMFloatTypeInContext(context.as_raw()) as *mut Type<AnyType>)
        }
    }

    pub fn f64<'ctx>(context: &'ctx Context<'cid>) -> &'ctx Type<'cid, AnyType> {
        unsafe {
            &*(LLVMDoubleTypeInContext(context.as_raw()) as *mut Type<AnyType>)
        }
    }

    pub fn i1<'ctx>(context: &'ctx Context<'cid>) -> &'ctx Type<'cid, AnyType> {
        unsafe {
            &*(LLVMInt1TypeInContext(context.as_raw()) as *mut Type<AnyType>)
        }
    }

    pub fn i8<'ctx>(context: &'ctx Context<'cid>) -> &'ctx Type<'cid, AnyType> {
        unsafe {
            &*(LLVMInt8TypeInContext(context.as_raw()) as *mut Type<AnyType>)
        }
    }

    pub fn i16<'ctx>(context: &'ctx Context<'cid>) -> &'ctx Type<'cid, AnyType> {
        unsafe {
            &*(LLVMInt16TypeInContext(context.as_raw()) as *mut Type<AnyType>)
        }
    }

    pub fn i32<'ctx>(context: &'ctx Context<'cid>) -> &'ctx Type<'cid, AnyType> {
        unsafe {
            &*(LLVMInt32TypeInContext(context.as_raw()) as *mut Type<AnyType>)
        }
    }

    pub fn i64<'ctx>(context: &'ctx Context<'cid>) -> &'ctx Type<'cid, AnyType> {
        unsafe {
            &*(LLVMInt64TypeInContext(context.as_raw()) as *mut Type<AnyType>)
        }
    }

    pub fn void<'ctx>(context: &'ctx Context<'cid>) -> &'ctx Type<'cid, AnyType> {
        unsafe {
            &*(LLVMVoidTypeInContext(context.as_raw()) as *mut Type<AnyType>)
        }
    }

    pub fn of_value<'a, 'mid, 'fid>(value: &'a Value<'cid, 'mid, 'fid>) -> &'a Type<'cid, AnyType> {
        unsafe {
            &*(LLVMTypeOf(value.as_raw()) as *mut Type<AnyType>)
        }
    }
}

impl<'cid, SubType> Type<'cid, SubType> {
    pub fn pointer<'ctx>(inner: &'ctx Type<'cid, SubType>, address_space: c_uint) -> &'ctx Type<'cid, PointerType<SubType>> {
        unsafe {
            &*(LLVMPointerType(inner.as_raw(), address_space) as *mut Type<PointerType<SubType>>)
        }
    }

    pub fn array<'ctx>(inner: &'ctx Type<'cid, SubType>, count: c_uint) -> &'ctx Type<'cid, ArrayType<SubType>> {
        unsafe {
            &*(LLVMArrayType(inner.as_raw(), count) as *mut Type<ArrayType<SubType>>)
        }
    }

    pub fn function<'ctx, ArgTy>(params: &[&'ctx Type<'cid, ArgTy>], ret: &'ctx Type<'cid, SubType>, var_arg: bool) -> &'ctx Type<'cid, FunctionType> {
        unsafe {
            &*(LLVMFunctionType(ret.as_raw(), params.as_ptr() as *mut LLVMTypeRef, params.len() as u32, var_arg as c_int) as *mut Type<FunctionType>)
        }
    }

    pub fn upcast<TargetTy>(&self) -> &Type<'cid, TargetTy> where SubType: Upcast<TargetTy> {
        unsafe {
            &*(self.as_raw() as *mut Type<TargetTy>)
        }
    }

    pub unsafe fn cast_unchecked<TargetTy>(&self) -> &Type<'cid, TargetTy> {
        &*(self.as_raw() as *mut Type<TargetTy>)
    }

    pub fn dump(&self) {
        unsafe {
            LLVMDumpType(self.as_raw())
        }
    }

    pub fn as_raw(&self) -> LLVMTypeRef {
        self as *const Type<SubType> as *mut Type<SubType> as LLVMTypeRef
    }
}

impl<'cid> Type<'cid, FunctionType> {
    pub fn is_var_arg(&self) -> bool {
        unsafe {
            LLVMIsFunctionVarArg(self.as_raw()) != 0
        }
    }
}

impl<'cid, PointeeTy> Type<'cid, PointerType<PointeeTy>> {
    pub fn pointee_ty(&self) -> &Type<'cid, PointeeTy> {
        unsafe {
            &*(LLVMGetElementType(self.as_raw()) as *mut Type<PointeeTy>)
        }
    }
}

impl<'cid, ElementTy> Type<'cid, ArrayType<ElementTy>> {
    pub fn element_ty(&self) -> &Type<'cid, ElementTy> {
        unsafe {
            &*(LLVMGetElementType(self.as_raw()) as *mut Type<ElementTy>)
        }
    }
}

pub unsafe trait Upcast<Target> { }
unsafe impl<T> Upcast<AnyType> for T { }
unsafe impl<GeneralPointeeTy, PointeeTy: Upcast<GeneralPointeeTy>> Upcast<PointerType<GeneralPointeeTy>> for PointerType<PointeeTy> { }
unsafe impl<GeneralElementTy, ElementTy: Upcast<GeneralElementTy>> Upcast<ArrayType<GeneralElementTy>> for ArrayType<ElementTy> { }

pub enum AnyType { }
pub struct PointerType<PointeeTy> {
    _marker: PhantomData<PointeeTy>
}
pub struct ArrayType<ElementTy> {
    _marker: PhantomData<ElementTy>
}
pub enum FunctionType { }
<|endoftext|>


<commit_before>use ::interconnect::*;
use ::peripherals::*;
use ::cpu::*;
use ::debugger::*;
use ::utils::read_bin;

use std::path::Path;

use std::rc::Rc;
use std::cell::RefCell;

extern crate sdl2;
use sdl2::pixels::PixelFormatEnum;
use sdl2::rect::Rect;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

use std::collections::HashMap;

#[derive(Hash, Eq, PartialEq, Debug)]
pub enum SpectrumKeycode {
    Num0,
    Num1,
    Num2,
    Num3,
    Num4,
    Num5,
    Num6,
    Num7,
    Num8,
    Num9,
    A,
    B,
    C,
    D,
    E,
    F,
    G,
    H,
    I,
    J,
    K,
    L,
    M,
    N,
    O,
    P,
    Q,
    R,
    S,
    T,
    U,
    V,
    W,
    X,
    Y,
    Z,
    Space,
    Enter,
    Caps,
    Symbol,

    NONE,
}

lazy_static! {
    static ref KEYBOARD_MAPPINGS: HashMap<Keycode,(SpectrumKeycode, SpectrumKeycode)> = {
        let mut m = HashMap::new();

        m.insert(Keycode::Escape,    (SpectrumKeycode::Num1,  SpectrumKeycode::Caps));
        m.insert(Keycode::Num1,      (SpectrumKeycode::Num1,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num2,      (SpectrumKeycode::Num2,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num3,      (SpectrumKeycode::Num3,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num4,      (SpectrumKeycode::Num4,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num5,      (SpectrumKeycode::Num5,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num6,      (SpectrumKeycode::Num6,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num7,      (SpectrumKeycode::Num7,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num8,      (SpectrumKeycode::Num8,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num9,      (SpectrumKeycode::Num9,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num0,      (SpectrumKeycode::Num0,  SpectrumKeycode::NONE));
        m.insert(Keycode::Minus,     (SpectrumKeycode::J,     SpectrumKeycode::Symbol));
        m.insert(Keycode::Equals,    (SpectrumKeycode::L,     SpectrumKeycode::Symbol));
        m.insert(Keycode::Backspace, (SpectrumKeycode::Num0,  SpectrumKeycode::Caps));

        m.insert(Keycode::Tab,       (SpectrumKeycode::Caps,  SpectrumKeycode::Symbol));
        m.insert(Keycode::Q,         (SpectrumKeycode::Q,     SpectrumKeycode::NONE));
        m.insert(Keycode::W,         (SpectrumKeycode::W,     SpectrumKeycode::NONE));
        m.insert(Keycode::E,         (SpectrumKeycode::E,     SpectrumKeycode::NONE));
        m.insert(Keycode::R,         (SpectrumKeycode::R,     SpectrumKeycode::NONE));
        m.insert(Keycode::T,         (SpectrumKeycode::T,     SpectrumKeycode::NONE));
        m.insert(Keycode::Y,         (SpectrumKeycode::Y,     SpectrumKeycode::NONE));
        m.insert(Keycode::U,         (SpectrumKeycode::U,     SpectrumKeycode::NONE));
        m.insert(Keycode::I,         (SpectrumKeycode::I,     SpectrumKeycode::NONE));
        m.insert(Keycode::O,         (SpectrumKeycode::O,     SpectrumKeycode::NONE));
        m.insert(Keycode::P,         (SpectrumKeycode::P,     SpectrumKeycode::NONE));

        m.insert(Keycode::CapsLock,  (SpectrumKeycode::Num2,  SpectrumKeycode::Caps));
        m.insert(Keycode::A,         (SpectrumKeycode::A,     SpectrumKeycode::NONE));
        m.insert(Keycode::S,         (SpectrumKeycode::S,     SpectrumKeycode::NONE));
        m.insert(Keycode::D,         (SpectrumKeycode::D,     SpectrumKeycode::NONE));
        m.insert(Keycode::F,         (SpectrumKeycode::F,     SpectrumKeycode::NONE));
        m.insert(Keycode::G,         (SpectrumKeycode::G,     SpectrumKeycode::NONE));
        m.insert(Keycode::H,         (SpectrumKeycode::H,     SpectrumKeycode::NONE));
        m.insert(Keycode::J,         (SpectrumKeycode::J,     SpectrumKeycode::NONE));
        m.insert(Keycode::K,         (SpectrumKeycode::K,     SpectrumKeycode::NONE));
        m.insert(Keycode::L,         (SpectrumKeycode::L,     SpectrumKeycode::NONE));
        m.insert(Keycode::Semicolon, (SpectrumKeycode::O,     SpectrumKeycode::Symbol));
        m.insert(Keycode::Quote,     (SpectrumKeycode::Num7,  SpectrumKeycode::Symbol));
        m.insert(Keycode::Hash,      (SpectrumKeycode::Num3,  SpectrumKeycode::Symbol));
        m.insert(Keycode::Return,    (SpectrumKeycode::Enter, SpectrumKeycode::NONE));

        m.insert(Keycode::LShift,    (SpectrumKeycode::NONE,  SpectrumKeycode::Caps));
        m.insert(Keycode::Z,         (SpectrumKeycode::Z,     SpectrumKeycode::NONE));
        m.insert(Keycode::X,         (SpectrumKeycode::X,     SpectrumKeycode::NONE));
        m.insert(Keycode::C,         (SpectrumKeycode::C,     SpectrumKeycode::NONE));
        m.insert(Keycode::V,         (SpectrumKeycode::V,     SpectrumKeycode::NONE));
        m.insert(Keycode::B,         (SpectrumKeycode::B,     SpectrumKeycode::NONE));
        m.insert(Keycode::N,         (SpectrumKeycode::N,     SpectrumKeycode::NONE));
        m.insert(Keycode::M,         (SpectrumKeycode::M,     SpectrumKeycode::NONE));
        m.insert(Keycode::Comma,     (SpectrumKeycode::N,     SpectrumKeycode::Symbol));
        m.insert(Keycode::Period,    (SpectrumKeycode::M,     SpectrumKeycode::Symbol));
        m.insert(Keycode::Slash,     (SpectrumKeycode::V,     SpectrumKeycode::Symbol));
        m.insert(Keycode::RShift,    (SpectrumKeycode::NONE,  SpectrumKeycode::Caps));

        m.insert(Keycode::LCtrl,     (SpectrumKeycode::NONE,  SpectrumKeycode::Symbol));
        m.insert(Keycode::LAlt,      (SpectrumKeycode::NONE,  SpectrumKeycode::Symbol));
        m.insert(Keycode::Space,     (SpectrumKeycode::Space, SpectrumKeycode::NONE));
        m.insert(Keycode::RAlt,      (SpectrumKeycode::NONE,  SpectrumKeycode::Symbol));
        m.insert(Keycode::RCtrl,     (SpectrumKeycode::NONE,  SpectrumKeycode::Symbol));
        m.insert(Keycode::Mode,      (SpectrumKeycode::NONE,  SpectrumKeycode::Symbol));

        m.insert(Keycode::Left,      (SpectrumKeycode::Num5,  SpectrumKeycode::Caps));
        m.insert(Keycode::Down,      (SpectrumKeycode::Num6,  SpectrumKeycode::Caps));
        m.insert(Keycode::Up,        (SpectrumKeycode::Num7,  SpectrumKeycode::Caps));
        m.insert(Keycode::Right,     (SpectrumKeycode::Num8,  SpectrumKeycode::Caps));
        m
    };
}

pub struct Machine {
    cpu: Rc<RefCell<Cpu>>,
    memory: Rc<RefCell<Memory>>,
    ula: Rc<RefCell<Ula>>,
    debug_on: bool,
}

impl Machine {
    pub fn new(start_in_debug: bool) -> Self {
        let rom0 = read_bin(Path::new("./roms/128-0.rom"));
        let rom1 = read_bin(Path::new("./roms/128-1.rom"));

        let memory = Rc::new(RefCell::new(MemoryBuilder::new()
            .rom0(rom0)
            .rom1(rom1)
            .finalize()));

        let ay = Rc::new(RefCell::new(Ay::new()));
        let ula = Rc::new(RefCell::new(Ula::new(memory.clone())));

        let interconnect = Interconnect::new(
            memory.clone(),
            ay.clone(),
            ula.clone());

        let cpu = Rc::new(RefCell::new(Cpu::new(interconnect)));

        Machine {
            cpu: cpu,
            memory: memory,
            ula: ula,
            debug_on: start_in_debug,
        }
    }

    pub fn run(&self) {
        let mut debugger = Debugger::new(
            self.cpu.clone(),
            self.memory.clone());

        let sdl_context = sdl2::init().unwrap();
        let video_subsystem = sdl_context.video().unwrap();

        let window = video_subsystem.window("rustz80emu", 256, 192)
            .position_centered()
            .build()
            .unwrap();

        let mut canvas = window.into_canvas().build().unwrap();

        let texture_creator = canvas.texture_creator();
        let mut texture = texture_creator.create_texture_streaming(
            PixelFormatEnum::RGB24, 256, 192).unwrap();

        let mut event_pump = sdl_context.event_pump().unwrap();

        'machine: loop {
            for event in event_pump.poll_iter() {
                match event {
                    Event::Quit {..} => {
                        break 'machine
                    },
                    Event::KeyDown { keycode:Some(k), ..} => {
                        match KEYBOARD_MAPPINGS.get(&k) {
                            Some(&(ref key1, ref key2)) => {
                                self.ula.borrow_mut().key_pressed(key1);
                                self.ula.borrow_mut().key_pressed(key2);
                            }
                            None => {}
                        }
                    },
                    Event::KeyUp { keycode:Some(k), ..} => {
                        match KEYBOARD_MAPPINGS.get(&k) {
                            Some(&(ref key1, ref key2)) => {
                                self.ula.borrow_mut().key_released(key1);
                                self.ula.borrow_mut().key_released(key2);
                            }
                            None => {}
                        }
                    }
                    _ => {}
                }
            }

            if self.debug_on { debugger.pre(); }

            if self.cpu.borrow().tcycles > 70908 {
                self.ula.borrow().display(&mut texture);

                canvas.clear();
                canvas.copy(&texture, None, Some(Rect::new(0, 0, 256, 192))).unwrap();
                canvas.present();
            }

            self.cpu.borrow_mut().handle_interrupts();
            self.cpu.borrow_mut().run_instruction();

            if self.debug_on { debugger.post(); }
        }
    }
}
<commit_msg>Double the graphical resolution<commit_after>use ::interconnect::*;
use ::peripherals::*;
use ::cpu::*;
use ::debugger::*;
use ::utils::read_bin;

use std::path::Path;

use std::rc::Rc;
use std::cell::RefCell;

extern crate sdl2;
use sdl2::pixels::PixelFormatEnum;
use sdl2::rect::Rect;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

use std::collections::HashMap;

#[derive(Hash, Eq, PartialEq, Debug)]
pub enum SpectrumKeycode {
    Num0,
    Num1,
    Num2,
    Num3,
    Num4,
    Num5,
    Num6,
    Num7,
    Num8,
    Num9,
    A,
    B,
    C,
    D,
    E,
    F,
    G,
    H,
    I,
    J,
    K,
    L,
    M,
    N,
    O,
    P,
    Q,
    R,
    S,
    T,
    U,
    V,
    W,
    X,
    Y,
    Z,
    Space,
    Enter,
    Caps,
    Symbol,

    NONE,
}

lazy_static! {
    static ref KEYBOARD_MAPPINGS: HashMap<Keycode,(SpectrumKeycode, SpectrumKeycode)> = {
        let mut m = HashMap::new();

        m.insert(Keycode::Escape,    (SpectrumKeycode::Num1,  SpectrumKeycode::Caps));
        m.insert(Keycode::Num1,      (SpectrumKeycode::Num1,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num2,      (SpectrumKeycode::Num2,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num3,      (SpectrumKeycode::Num3,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num4,      (SpectrumKeycode::Num4,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num5,      (SpectrumKeycode::Num5,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num6,      (SpectrumKeycode::Num6,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num7,      (SpectrumKeycode::Num7,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num8,      (SpectrumKeycode::Num8,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num9,      (SpectrumKeycode::Num9,  SpectrumKeycode::NONE));
        m.insert(Keycode::Num0,      (SpectrumKeycode::Num0,  SpectrumKeycode::NONE));
        m.insert(Keycode::Minus,     (SpectrumKeycode::J,     SpectrumKeycode::Symbol));
        m.insert(Keycode::Equals,    (SpectrumKeycode::L,     SpectrumKeycode::Symbol));
        m.insert(Keycode::Backspace, (SpectrumKeycode::Num0,  SpectrumKeycode::Caps));

        m.insert(Keycode::Tab,       (SpectrumKeycode::Caps,  SpectrumKeycode::Symbol));
        m.insert(Keycode::Q,         (SpectrumKeycode::Q,     SpectrumKeycode::NONE));
        m.insert(Keycode::W,         (SpectrumKeycode::W,     SpectrumKeycode::NONE));
        m.insert(Keycode::E,         (SpectrumKeycode::E,     SpectrumKeycode::NONE));
        m.insert(Keycode::R,         (SpectrumKeycode::R,     SpectrumKeycode::NONE));
        m.insert(Keycode::T,         (SpectrumKeycode::T,     SpectrumKeycode::NONE));
        m.insert(Keycode::Y,         (SpectrumKeycode::Y,     SpectrumKeycode::NONE));
        m.insert(Keycode::U,         (SpectrumKeycode::U,     SpectrumKeycode::NONE));
        m.insert(Keycode::I,         (SpectrumKeycode::I,     SpectrumKeycode::NONE));
        m.insert(Keycode::O,         (SpectrumKeycode::O,     SpectrumKeycode::NONE));
        m.insert(Keycode::P,         (SpectrumKeycode::P,     SpectrumKeycode::NONE));

        m.insert(Keycode::CapsLock,  (SpectrumKeycode::Num2,  SpectrumKeycode::Caps));
        m.insert(Keycode::A,         (SpectrumKeycode::A,     SpectrumKeycode::NONE));
        m.insert(Keycode::S,         (SpectrumKeycode::S,     SpectrumKeycode::NONE));
        m.insert(Keycode::D,         (SpectrumKeycode::D,     SpectrumKeycode::NONE));
        m.insert(Keycode::F,         (SpectrumKeycode::F,     SpectrumKeycode::NONE));
        m.insert(Keycode::G,         (SpectrumKeycode::G,     SpectrumKeycode::NONE));
        m.insert(Keycode::H,         (SpectrumKeycode::H,     SpectrumKeycode::NONE));
        m.insert(Keycode::J,         (SpectrumKeycode::J,     SpectrumKeycode::NONE));
        m.insert(Keycode::K,         (SpectrumKeycode::K,     SpectrumKeycode::NONE));
        m.insert(Keycode::L,         (SpectrumKeycode::L,     SpectrumKeycode::NONE));
        m.insert(Keycode::Semicolon, (SpectrumKeycode::O,     SpectrumKeycode::Symbol));
        m.insert(Keycode::Quote,     (SpectrumKeycode::Num7,  SpectrumKeycode::Symbol));
        m.insert(Keycode::Hash,      (SpectrumKeycode::Num3,  SpectrumKeycode::Symbol));
        m.insert(Keycode::Return,    (SpectrumKeycode::Enter, SpectrumKeycode::NONE));

        m.insert(Keycode::LShift,    (SpectrumKeycode::NONE,  SpectrumKeycode::Caps));
        m.insert(Keycode::Z,         (SpectrumKeycode::Z,     SpectrumKeycode::NONE));
        m.insert(Keycode::X,         (SpectrumKeycode::X,     SpectrumKeycode::NONE));
        m.insert(Keycode::C,         (SpectrumKeycode::C,     SpectrumKeycode::NONE));
        m.insert(Keycode::V,         (SpectrumKeycode::V,     SpectrumKeycode::NONE));
        m.insert(Keycode::B,         (SpectrumKeycode::B,     SpectrumKeycode::NONE));
        m.insert(Keycode::N,         (SpectrumKeycode::N,     SpectrumKeycode::NONE));
        m.insert(Keycode::M,         (SpectrumKeycode::M,     SpectrumKeycode::NONE));
        m.insert(Keycode::Comma,     (SpectrumKeycode::N,     SpectrumKeycode::Symbol));
        m.insert(Keycode::Period,    (SpectrumKeycode::M,     SpectrumKeycode::Symbol));
        m.insert(Keycode::Slash,     (SpectrumKeycode::V,     SpectrumKeycode::Symbol));
        m.insert(Keycode::RShift,    (SpectrumKeycode::NONE,  SpectrumKeycode::Caps));

        m.insert(Keycode::LCtrl,     (SpectrumKeycode::NONE,  SpectrumKeycode::Symbol));
        m.insert(Keycode::LAlt,      (SpectrumKeycode::NONE,  SpectrumKeycode::Symbol));
        m.insert(Keycode::Space,     (SpectrumKeycode::Space, SpectrumKeycode::NONE));
        m.insert(Keycode::RAlt,      (SpectrumKeycode::NONE,  SpectrumKeycode::Symbol));
        m.insert(Keycode::RCtrl,     (SpectrumKeycode::NONE,  SpectrumKeycode::Symbol));
        m.insert(Keycode::Mode,      (SpectrumKeycode::NONE,  SpectrumKeycode::Symbol));

        m.insert(Keycode::Left,      (SpectrumKeycode::Num5,  SpectrumKeycode::Caps));
        m.insert(Keycode::Down,      (SpectrumKeycode::Num6,  SpectrumKeycode::Caps));
        m.insert(Keycode::Up,        (SpectrumKeycode::Num7,  SpectrumKeycode::Caps));
        m.insert(Keycode::Right,     (SpectrumKeycode::Num8,  SpectrumKeycode::Caps));
        m
    };
}

pub struct Machine {
    cpu: Rc<RefCell<Cpu>>,
    memory: Rc<RefCell<Memory>>,
    ula: Rc<RefCell<Ula>>,
    debug_on: bool,
}

impl Machine {
    pub fn new(start_in_debug: bool) -> Self {
        let rom0 = read_bin(Path::new("./roms/128-0.rom"));
        let rom1 = read_bin(Path::new("./roms/128-1.rom"));

        let memory = Rc::new(RefCell::new(MemoryBuilder::new()
            .rom0(rom0)
            .rom1(rom1)
            .finalize()));

        let ay = Rc::new(RefCell::new(Ay::new()));
        let ula = Rc::new(RefCell::new(Ula::new(memory.clone())));

        let interconnect = Interconnect::new(
            memory.clone(),
            ay.clone(),
            ula.clone());

        let cpu = Rc::new(RefCell::new(Cpu::new(interconnect)));

        Machine {
            cpu: cpu,
            memory: memory,
            ula: ula,
            debug_on: start_in_debug,
        }
    }

    pub fn run(&self) {
        let mut debugger = Debugger::new(
            self.cpu.clone(),
            self.memory.clone());

        let sdl_context = sdl2::init().unwrap();
        let video_subsystem = sdl_context.video().unwrap();

        let window = video_subsystem.window("rustz80emu", 512, 384)
            .position_centered()
            .build()
            .unwrap();

        let mut canvas = window.into_canvas().build().unwrap();

        let texture_creator = canvas.texture_creator();
        let mut texture = texture_creator.create_texture_streaming(
            PixelFormatEnum::RGB24, 256, 192).unwrap();

        let mut event_pump = sdl_context.event_pump().unwrap();

        'machine: loop {
            for event in event_pump.poll_iter() {
                match event {
                    Event::Quit {..} => {
                        break 'machine
                    },
                    Event::KeyDown { keycode:Some(k), ..} => {
                        match KEYBOARD_MAPPINGS.get(&k) {
                            Some(&(ref key1, ref key2)) => {
                                self.ula.borrow_mut().key_pressed(key1);
                                self.ula.borrow_mut().key_pressed(key2);
                            }
                            None => {}
                        }
                    },
                    Event::KeyUp { keycode:Some(k), ..} => {
                        match KEYBOARD_MAPPINGS.get(&k) {
                            Some(&(ref key1, ref key2)) => {
                                self.ula.borrow_mut().key_released(key1);
                                self.ula.borrow_mut().key_released(key2);
                            }
                            None => {}
                        }
                    }
                    _ => {}
                }
            }

            if self.debug_on { debugger.pre(); }

            if self.cpu.borrow().tcycles > 70908 {
                self.ula.borrow().display(&mut texture);

                canvas.clear();
                canvas.copy(&texture, None, Some(Rect::new(0, 0, 512, 384))).unwrap();
                canvas.present();
            }

            self.cpu.borrow_mut().handle_interrupts();
            self.cpu.borrow_mut().run_instruction();

            if self.debug_on { debugger.post(); }
        }
    }
}
<|endoftext|>


<commit_before>//! Parser module for Textile language.

mod attributes;
mod block;
mod inline;
mod patterns;

use into_string::*;
use parser::block::parse_blocks;
use std::collections::HashMap;

/// Vector of Textile attributes, e.g. classes, ID's or CSS styles.
pub type Attributes = Vec<Attribute>;

/// Block element, e.g. heading, paragraph or code block.
#[derive(Debug, PartialEq)]
pub enum Block {
    /// Block quotation, e.g. `bq. Some quote`.
    BlockQuotation {
        attributes: Attributes,
        cite: String,
        elements: Vec<Block>,
    },
    /// Code block, e.g. `bc. print("Hello World")`.
    CodeBlock {
        attributes: Attributes,
        code: String,
    },
    /// Comment block.
    Comment(Vec<String>),
    /// Heading, e.g. `h3. Some text`.
    Heading {
        attributes: Attributes,
        elements: Vec<Inline>,
        level: u8,
    },
    /// Disable Textile formatting in a block of text.
    NoTextileBlock(Vec<String>),
    /// Paragraph, e.g. `p. Some text` or `Some text`.
    Paragraph {
        attributes: Attributes,
        elements: Vec<Inline>,
        starts_with_p: bool,
    },
    Pre {
        attributes: Attributes,
        lines: Vec<String>,
    },
}

/// Inline element, e.g. bold text, link or image.
#[derive(Debug, PartialEq)]
pub enum Inline {
    /// Abbreviation, e.g. `ABBR(Abbreviation)`.
    Abbreviation {
        abbr: String,
        transcript: String,
    },
    /// Bold text, e.g. `*Text*` or `**Text**`.
    Bold {
        attributes: Attributes,
        elements: Vec<Inline>,
        tag_type: BoldTagType,
    },
    /// Line break. Converts to `<br>` tag in HTML.
    Break,
    /// Citation, e.g. `??Some citation??`.
    Citation {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// Code, e.g. `@puts "Hello world!"@`.
    Code(String),
    /// Image, e.g. `!http://example.com/image.jpg(Image)!`.
    Image {
        attributes: Attributes,
        alt: String,
        href: String,
        src: String,
    },
    /// Italic text, e.g. `_Text_` or `__Text__`.
    Italic {
        attributes: Attributes,
        tag_type: ItalicTagType,
        elements: Vec<Inline>,
    },
    /// Link, e.g. `"Link":http://example.com`.
    Link {
        attributes: Attributes,
        elements: Vec<Inline>,
        href: String,
        title: String,
    },
    /// Span element, e.g. `%Span text%`.
    Span {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// Strikethrough text, e.g. `-Text-`.
    Strikethrough {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// Subscript text, e.g. `~Text~`.
    Subscript {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// Superscript text, e.g. `^Text^`.
    Superscript {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// String with text.
    Text(String),
    /// Underlined text, e.g. `+Text+`.
    Underlined {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
}

/// Tag type for bold text.
#[derive(Debug, PartialEq)]
pub enum BoldTagType {
    /// Converts into HTML `<b>` tag.
    Bold,
    /// Converts into HTML `<strong>` tag.
    Strong,
}

/// Tag type for italic text.
#[derive(Debug, PartialEq)]
pub enum ItalicTagType {
    /// Converts into HTML `<em>` tag.
    Emphasis,
    /// Converts into HTML `<i>` tag.
    Italic,
}

/// Textile attribute.
#[derive(Debug, Clone, PartialEq)]
pub enum Attribute {
    /// Image align. Convertes into HTML `align` attribute.
    Align(String),
    /// Vector of HTML classes. Converts into HTML `class` attribute.
    Class(Vec<String>),
    /// Converts into HTML `id` attribute.
    Id(String),
    /// Converts into HTML `lang` attribute.
    Language(String),
    /// CSS styles. Converts into HTML `style` attribute.
    Style(HashMap<String, String>)
}

/// Splits text into tokens. Accepts `&str`, `String` or `Path` data type. Returns vector of block elements.
///
/// # Example
///
/// ```rust
/// use textile::parser::*;
///
/// let text = "h1. _String with text_.";
/// assert_eq!(parse(text), vec![
///     Block::Heading {
///         attributes: vec![],
///         elements: vec![
///             Inline::Italic {
///                 attributes: vec![],
///                 tag_type: ItalicTagType::Emphasis,
///                 elements: vec![
///                     Inline::Text("String with text".to_string())
///                 ]
///             },
///             Inline::Text(".".to_string())
///         ],
///         level: 1
///     }
/// ]);
/// ```
pub fn parse<S: IntoString>(text: S) -> Vec<Block> {
    parse_blocks(&text.into_string().lines().collect::<Vec<&str>>())
}
<commit_msg>Reorder 'tag_type' field in 'Inline::Italic' variant<commit_after>//! Parser module for Textile language.

mod attributes;
mod block;
mod inline;
mod patterns;

use into_string::*;
use parser::block::parse_blocks;
use std::collections::HashMap;

/// Vector of Textile attributes, e.g. classes, ID's or CSS styles.
pub type Attributes = Vec<Attribute>;

/// Block element, e.g. heading, paragraph or code block.
#[derive(Debug, PartialEq)]
pub enum Block {
    /// Block quotation, e.g. `bq. Some quote`.
    BlockQuotation {
        attributes: Attributes,
        cite: String,
        elements: Vec<Block>,
    },
    /// Code block, e.g. `bc. print("Hello World")`.
    CodeBlock {
        attributes: Attributes,
        code: String,
    },
    /// Comment block.
    Comment(Vec<String>),
    /// Heading, e.g. `h3. Some text`.
    Heading {
        attributes: Attributes,
        elements: Vec<Inline>,
        level: u8,
    },
    /// Disable Textile formatting in a block of text.
    NoTextileBlock(Vec<String>),
    /// Paragraph, e.g. `p. Some text` or `Some text`.
    Paragraph {
        attributes: Attributes,
        elements: Vec<Inline>,
        starts_with_p: bool,
    },
    Pre {
        attributes: Attributes,
        lines: Vec<String>,
    },
}

/// Inline element, e.g. bold text, link or image.
#[derive(Debug, PartialEq)]
pub enum Inline {
    /// Abbreviation, e.g. `ABBR(Abbreviation)`.
    Abbreviation {
        abbr: String,
        transcript: String,
    },
    /// Bold text, e.g. `*Text*` or `**Text**`.
    Bold {
        attributes: Attributes,
        elements: Vec<Inline>,
        tag_type: BoldTagType,
    },
    /// Line break. Converts to `<br>` tag in HTML.
    Break,
    /// Citation, e.g. `??Some citation??`.
    Citation {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// Code, e.g. `@puts "Hello world!"@`.
    Code(String),
    /// Image, e.g. `!http://example.com/image.jpg(Image)!`.
    Image {
        attributes: Attributes,
        alt: String,
        href: String,
        src: String,
    },
    /// Italic text, e.g. `_Text_` or `__Text__`.
    Italic {
        attributes: Attributes,
        elements: Vec<Inline>,
        tag_type: ItalicTagType,
    },
    /// Link, e.g. `"Link":http://example.com`.
    Link {
        attributes: Attributes,
        elements: Vec<Inline>,
        href: String,
        title: String,
    },
    /// Span element, e.g. `%Span text%`.
    Span {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// Strikethrough text, e.g. `-Text-`.
    Strikethrough {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// Subscript text, e.g. `~Text~`.
    Subscript {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// Superscript text, e.g. `^Text^`.
    Superscript {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
    /// String with text.
    Text(String),
    /// Underlined text, e.g. `+Text+`.
    Underlined {
        attributes: Attributes,
        elements: Vec<Inline>,
    },
}

/// Tag type for bold text.
#[derive(Debug, PartialEq)]
pub enum BoldTagType {
    /// Converts into HTML `<b>` tag.
    Bold,
    /// Converts into HTML `<strong>` tag.
    Strong,
}

/// Tag type for italic text.
#[derive(Debug, PartialEq)]
pub enum ItalicTagType {
    /// Converts into HTML `<em>` tag.
    Emphasis,
    /// Converts into HTML `<i>` tag.
    Italic,
}

/// Textile attribute.
#[derive(Debug, Clone, PartialEq)]
pub enum Attribute {
    /// Image align. Convertes into HTML `align` attribute.
    Align(String),
    /// Vector of HTML classes. Converts into HTML `class` attribute.
    Class(Vec<String>),
    /// Converts into HTML `id` attribute.
    Id(String),
    /// Converts into HTML `lang` attribute.
    Language(String),
    /// CSS styles. Converts into HTML `style` attribute.
    Style(HashMap<String, String>)
}

/// Splits text into tokens. Accepts `&str`, `String` or `Path` data type. Returns vector of block elements.
///
/// # Example
///
/// ```rust
/// use textile::parser::*;
///
/// let text = "h1. _String with text_.";
/// assert_eq!(parse(text), vec![
///     Block::Heading {
///         attributes: vec![],
///         elements: vec![
///             Inline::Italic {
///                 attributes: vec![],
///                 tag_type: ItalicTagType::Emphasis,
///                 elements: vec![
///                     Inline::Text("String with text".to_string())
///                 ]
///             },
///             Inline::Text(".".to_string())
///         ],
///         level: 1
///     }
/// ]);
/// ```
pub fn parse<S: IntoString>(text: S) -> Vec<Block> {
    parse_blocks(&text.into_string().lines().collect::<Vec<&str>>())
}
<|endoftext|>


<commit_before>use rusqlite::Connection;

#[derive(Debug)]
pub enum Version {
    Version1,
    Version2,
}

#[derive(Debug)]
pub struct Job {
    pub id: i32,
    pub fk_file: i32,
    pub name: String,
}

trait JobModuleTrait {
    // Static method signature; `Self` refers to the implementor type.
    fn new(name: &'static str) -> Self;
    fn hashmap(conn: &Connection) -> Vec<Job>;
    // fn update_hashcache(&self, &hashcache) -> &'static str;
}

pub fn table_create_job(conn: &Connection) {
    let load_table = conn.execute(
        "CREATE TABLE JOB (
                  id              INTEGER PRIMARY KEY ASC,
                  fk_file         INTEGER NOT NULL,
                  name            TEXT NOT NULL UNIQUE,
                  FOREIGN KEY(fk_file) REFERENCES FS_FILE(id) ON UPDATE CASCADE
                  )",
        &[],
    );
    if load_table.is_err() {
        error!("table_create_job Failed {:?}", load_table);
        return;
    }
    load_table.unwrap();
}

pub fn insert_job(
    conn: &Connection,
    fk_file: &i32,
    name: &String,
) -> Result<Version, &'static str> {
    let me = Job {
        id: 0,
        fk_file: fk_file.clone(),
        name: name.clone(),
    };
    let load_instance = conn.execute(
        "INSERT INTO JOB (name, fk_file)
                  VALUES (?1, ?2)",
        &[&me.name, fk_file],
    );
    if load_instance.is_err() {
        return Err("Insert failed");
    }
    load_instance.unwrap();
    return Ok(Version::Version1);
}

pub fn list_job(conn: &Connection) -> Vec<Job> {
    let mut stmt = conn.prepare("SELECT id, fk_file, name FROM JOB").unwrap();
    let wraped_job_iter = stmt.query_map(&[], |row| Job {
        id: row.get(0),
        fk_file: row.get(1),
        name: row.get(2),
    });
    let mut items = Vec::<Job>::new();
    if wraped_job_iter.is_err() {
        return items;
    }
    let job_iter = wraped_job_iter.unwrap();
    for person in job_iter {
        items.push(person.unwrap());
    }
    return items;
}

pub fn pk_job_by_name(
    conn: &Connection,
    name: &String,
    pk: &mut i32,
) -> Result<Version, &'static str> {
    let bill = name.clone();
    let mut stmt = conn.prepare("SELECT id, fk_file, name  FROM JOB WHERE name = ?1")
        .unwrap();
    let job_iter = stmt.query_map(&[&bill], |row| Job {
        id: row.get(0),
        fk_file: row.get(1),
        name: row.get(2),
    }).unwrap();
    let mut found = 0;
    for person in job_iter {
        let bill = person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found == 1 {
        return Ok(Version::Version1);
    }
    return Err("None found");
}
<commit_msg>Beutify the rust code<commit_after>use rusqlite::Connection;

#[derive(Debug)]
pub enum Version {
    Version1,
    Version2,
}

#[derive(Debug)]
pub struct Job {
    pub id: i32,
    pub fk_file: i32,
    pub name: String,
}

trait JobModuleTrait {
    // Static method signature; `Self` refers to the implementor type.
    fn new(name: &'static str) -> Self;
    fn hashmap(conn: &Connection) -> Vec<Job>;
    // fn update_hashcache(&self, &hashcache) -> &'static str;
}

pub fn table_create_job(conn: &Connection) {
    let load_table = conn.execute(
        "CREATE TABLE JOB (
                  id              INTEGER PRIMARY KEY ASC,
                  fk_file         INTEGER NOT NULL,
                  name            TEXT NOT NULL UNIQUE,
                  FOREIGN KEY(fk_file) REFERENCES FS_FILE(id) ON UPDATE CASCADE
                  )",
        &[],
    );
    if load_table.is_err() {
        error!("table_create_job Failed {:?}", load_table);
        return;
    }
    load_table.unwrap();
}

pub fn insert_job(
    conn: &Connection,
    fk_file: &i32,
    name: &String,
) -> Result<Version, &'static str> {
    let me = Job {
        id: 0,
        fk_file: fk_file.clone(),
        name: name.clone(),
    };
    let load_instance = conn.execute(
        "INSERT INTO JOB (name, fk_file)
                  VALUES (?1, ?2)",
        &[&me.name, fk_file],
    );
    if load_instance.is_err() {
        return Err("Insert failed");
    }
    load_instance.unwrap();
    return Ok(Version::Version1);
}

pub fn list_job(conn: &Connection) -> Vec<Job> {
    let mut stmt = conn.prepare("SELECT id, fk_file, name FROM JOB").unwrap();
    let wraped_job_iter = stmt.query_map(&[], |row| Job {
        id: row.get(0),
        fk_file: row.get(1),
        name: row.get(2),
    });
    let mut items = Vec::<Job>::new();
    if wraped_job_iter.is_err() {
        return items;
    }
    let job_iter = wraped_job_iter.unwrap();
    for person in job_iter {
        items.push(person.unwrap());
    }
    return items;
}

pub fn pk_job_by_name(
    conn: &Connection,
    name: &String,
    pk: &mut i32,
) -> Result<Version, &'static str> {
    let bill = name.clone();
    let mut stmt = conn
        .prepare("SELECT id, fk_file, name  FROM JOB WHERE name = ?1")
        .unwrap();
    let job_iter =
        stmt.query_map(&[&bill], |row| Job {
            id: row.get(0),
            fk_file: row.get(1),
            name: row.get(2),
        }).unwrap();
    let mut found = 0;
    for person in job_iter {
        let bill = person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found == 1 {
        return Ok(Version::Version1);
    }
    return Err("None found");
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use node::{Prim, Node, Bool, rint, rcar, rcdar, rcddar, rcdr, rsym, rcell, rquote, rbool};
use env::Env;
use evaluator::*;
use error::EvalError;

pub fn prim_let(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    let let_args = try!(rcar(args));
    let body = try!(rcdar(args));
    let (aargs, vargs) = transform(&let_args);
    let lambda = Node::Prim(Prim::Lambda(renv.clone(), Rc::new(vargs), Rc::new(body)));
    eval(renv, &rcell(rquote(lambda), aargs))
}

fn transform(node: &Node) -> (Node, Node) {
    match node {
        &Node::Cell(ref v, ref r) => {
            let nv = rcar(v).unwrap();
            let nr = rcdar(v).unwrap();
            let (ar, vr) = transform(r);
            (rcell(nr, ar), rcell(nv, vr))
        }
        _ => (Node::Nil, Node::Nil)
    }
}

pub fn prim_lambda(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    let lambda_args = try!(rcar(args));
    let body = rcell(rsym("progn"), try!(rcdr(args)));

    Ok(Node::Prim(Prim::Lambda(renv.clone(), Rc::new(lambda_args), Rc::new(body))))
}

pub fn prim_if(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    let cond = try!(rcar(args).and_then( |ref v| eval(renv, v) ));
    let clause = if cond == Node::Bool(Bool::False) {
        rcddar(args)
    } else {
        rcdar(args)
    };
    clause.and_then( |ref v| eval(renv, v))
}

pub fn prim_progn(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    match *args {
        Node::Cell(ref car, ref cdr) => {
            let ret = try!(eval(renv, car));
            let rest = try!(prim_progn(renv, cdr));
            Ok(if rest == Node::Nil { ret } else  { rest })
        }
        ref x => Ok(x.clone())
    }
}

pub fn prim_quote(_: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    rcar(args)
}

pub fn prim_define(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    match *args {
        Node::Cell(ref car, ref cdr) => {
            if let Node::Sym(ref s) = **car {
                let ccdr = try!(rcar(cdr));
                let ret = try!(eval(renv, &ccdr));
                renv.register(s.to_string(), ret.clone());
                return Ok(ret);
            }
        },
        _ => ()
    }
    Err(EvalError::E)
}

pub fn prim_eq(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    let ref eargs = try!(eval_list(renv, args));
    let ref car = try!(rcar(eargs));
    let ref cdr = try!(rcdr(eargs));
    Ok(rbool(try!(do_eq(car, cdr))))
}

pub fn prim_mul(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    Ok(rint(do_mul(&try!(eval_list(renv, args)))))
}

pub fn prim_sub(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    let lst = try!(eval_list(renv, args));
    match lst {
        Node::Cell(ref car, ref cdr) => {
            if let Node::Int(base) = **car {
                return Ok(rint(do_sub(base, cdr)))
            }
        },
        _ => ()
    }

    Err(EvalError::E)
}

pub fn prim_add(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    Ok(rint(do_add(&try!(eval_list(renv, args)))))
}

pub fn do_eq(l: &Node, r: &Node) -> EvalResult<bool> {
    match (l, r) {
        (ref rv@&Node::Int(_), &Node::Cell(ref v1, ref v2)) => {
            Ok(try!(do_eq(v1, v2)) && try!(do_eq(v1, rv)))
        },
        (&Node::Int(v1), &Node::Int(v2)) => Ok(v1 == v2),
        (_, &Node::Nil) => Ok(true),
        (_, _) => Err(EvalError::WrongTypeArg)
    }
}

fn do_mul(lst: &Node) -> i32 {
    match *lst {
        Node::Cell(ref car, ref cdr) => do_mul(car) * do_mul(cdr),
        Node::Int(k) => k,
        _ => 1
    }
}

fn do_sub(base: i32, lst: &Node) -> i32 {
    match *lst {
        Node::Cell(ref car, ref cdr) => {
            if let Node::Int(k) = **car {
                do_sub(base - k, cdr)
            } else {
                base
            }
        },
        _ => base
    }
}

fn do_add(lst: &Node) -> i32 {
    match *lst {
        Node::Cell(ref car, ref cdr) => do_add(car) + do_add(cdr),
        Node::Int(k) => k,
        _ => 0
    }
}
<commit_msg>Refactor to use a result of evaluation<commit_after>use std::rc::Rc;
use node::{Prim, Node, Bool, rint, rcar, rcdar, rcddar, rcdr, rsym, rcell, rquote, rbool};
use env::Env;
use evaluator::*;
use error::EvalError;

pub fn prim_let(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    let let_args = try!(rcar(args));
    let body = try!(rcdar(args));
    let (aargs, vargs) = transform(&let_args);
    let lambda = Node::Prim(Prim::Lambda(renv.clone(), Rc::new(vargs), Rc::new(body)));
    eval(renv, &rcell(rquote(lambda), aargs))
}

fn transform(node: &Node) -> (Node, Node) {
    match node {
        &Node::Cell(ref v, ref r) => {
            let nv = rcar(v).unwrap();
            let nr = rcdar(v).unwrap();
            let (ar, vr) = transform(r);
            (rcell(nr, ar), rcell(nv, vr))
        }
        _ => (Node::Nil, Node::Nil)
    }
}

pub fn prim_lambda(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    let lambda_args = try!(rcar(args));
    let body = rcell(rsym("progn"), try!(rcdr(args)));

    Ok(Node::Prim(Prim::Lambda(renv.clone(), Rc::new(lambda_args), Rc::new(body))))
}

pub fn prim_if(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    let cond = try!(rcar(args).and_then( |ref v| eval(renv, v) ));
    let clause = if cond == Node::Bool(Bool::False) {
        rcddar(args)
    } else {
        rcdar(args)
    };
    clause.and_then( |ref v| eval(renv, v))
}

pub fn prim_progn(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    match *args {
        Node::Cell(ref car, ref cdr) => {
            let ret = try!(eval(renv, car));
            let rest = try!(prim_progn(renv, cdr));
            Ok(if rest == Node::Nil { ret } else  { rest })
        }
        ref x => Ok(x.clone())
    }
}

pub fn prim_quote(_: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    rcar(args)
}

pub fn prim_define(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    match *args {
        Node::Cell(ref car, ref cdr) => {
            if let Node::Sym(ref s) = **car {
                let ccdr = try!(rcar(cdr));
                let ret = try!(eval(renv, &ccdr));
                renv.register(s.to_string(), ret.clone());
                return Ok(ret);
            }
        },
        _ => ()
    }
    Err(EvalError::E)
}

pub fn prim_eq(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    let ref eargs = try!(eval_list(renv, args));
    let ref car = try!(rcar(eargs));
    let ref cdr = try!(rcdr(eargs));
    Ok(rbool(try!(do_eq(car, cdr))))
}

pub fn prim_mul(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    let ret = try!(eval_list(renv, args).and_then( |ref v| do_mul(v) ));
    Ok(rint(ret))
}

pub fn prim_sub(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    let ref eargs = try!(eval_list(renv, args));
    let ref car = try!(rcar(eargs));
    let ref cdr = try!(rcdr(eargs));
    Ok(rint(try!(do_sub(car, cdr))))
}

pub fn prim_add(renv: &mut Env<Node>, args: &Node) -> EvalResult<Node> {
    let ret = try!(eval_list(renv, args).and_then( |ref v| do_add(v) ));
    Ok(rint(ret))
}

pub fn do_eq(l: &Node, r: &Node) -> EvalResult<bool> {
    match (l, r) {
        (ref rv@&Node::Int(_), &Node::Cell(ref v1, ref v2)) => {
            Ok(try!(do_eq(v1, v2)) && try!(do_eq(v1, rv)))
        },
        (&Node::Int(v1), &Node::Int(v2)) => Ok(v1 == v2),
        (_, &Node::Nil) => Ok(true),
        (_, _) => Err(EvalError::WrongTypeArg)
    }
}

fn do_mul(lst: &Node) -> EvalResult<i32> {
    match *lst {
        Node::Cell(ref car, ref cdr) => Ok(try!(do_mul(car)) * try!(do_mul(cdr))),
        Node::Int(k) => Ok(k),
        Node::Nil => Ok(1),
        _ => Err(EvalError::WrongTypeArg)
    }
}

fn do_sub(base: &Node, rest: &Node) -> EvalResult<i32> {
    match (base, rest) {
        (ref n@&Node::Int(_), &Node::Cell(ref v1, ref v2)) => {
            let ref re = Node::Int(try!(do_sub(n, v1)));
            do_sub(re, v2)
        }
        (&Node::Int(v1), &Node::Int(v2)) => Ok(v1 - v2),
        (&Node::Int(v), &Node::Nil) => Ok(v),
        (_, _) => Err(EvalError::WrongTypeArg)
    }
}

fn do_add(lst: &Node) -> EvalResult<i32> {
    match *lst {
        Node::Cell(ref car, ref cdr) => Ok(try!(do_add(car)) + try!(do_add(cdr))),
        Node::Int(k) => Ok(k),
        Node::Nil => Ok(0),
        _ => Err(EvalError::WrongTypeArg)
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomFn;
use std::mem;

use block::Block;
use runtime::{Class, Object, Sel, Super, self};

/*
 The Sized bound on Message is unfortunate; ideally, objc objects would not be
 treated as Sized. However, rust won't allow casting a dynamically-sized type
 pointer to an Object pointer, because dynamically-sized types can have fat
 pointers (two words) instead of real pointers.
 */
/// Types that may be sent Objective-C messages.
/// For example: objects, classes, and blocks.
pub unsafe trait Message : PhantomFn<Self> { }

unsafe impl Message for Object { }

unsafe impl Message for Class { }

unsafe impl<A, R> Message for Block<A, R> { }

#[cfg(target_arch = "x86_64")]
fn msg_send_fn<R>() -> unsafe extern fn(*mut Object, Sel, ...) -> R {
    if mem::size_of::<R>() <= 16 {
        unsafe { mem::transmute(runtime::objc_msgSend) }
    } else {
        unsafe { mem::transmute(runtime::objc_msgSend_stret) }
    }
}

#[cfg(target_arch = "x86_64")]
fn msg_send_super_fn<R>() -> unsafe extern fn(*const Super, Sel, ...) -> R {
    if mem::size_of::<R>() <= 16 {
        unsafe { mem::transmute(runtime::objc_msgSendSuper) }
    } else {
        unsafe { mem::transmute(runtime::objc_msgSendSuper_stret) }
    }
}

/// Types that may be used as the arguments of an Objective-C message.
pub trait MessageArguments {
    /// Sends a message to the given obj with the given selector and self as
    /// the arguments.
    ///
    /// The correct version of `objc_msgSend` will be chosen based on the
    /// return type. For more information, see Apple's documenation:
    /// https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/index.html#//apple_ref/doc/uid/TP40001418-CH1g-88778
    ///
    /// It is recommended to use the `msg_send!` macro rather than calling this
    /// method directly.
    unsafe fn send<T, R>(self, obj: *mut T, sel: Sel) -> R where T: Message;

    /// Sends a message to the superclass of an instance of a class with self
    /// as the arguments.
    unsafe fn send_super<T, R>(self, obj: *mut T, superclass: &Class, sel: Sel) -> R
            where T: Message;
}

macro_rules! message_args_impl {
    ($($a:ident : $t:ident),*) => (
        impl<$($t),*> MessageArguments for ($($t,)*) {
            unsafe fn send<T, R>(self, obj: *mut T, sel: Sel) -> R where T: Message {
                let msg_send_fn = msg_send_fn::<R>();
                let msg_send_fn: unsafe extern fn(*mut Object, Sel $(, $t)*) -> R =
                    mem::transmute(msg_send_fn);
                let ($($a,)*) = self;
                msg_send_fn(obj as *mut Object, sel $(, $a)*)
            }

            unsafe fn send_super<T, R>(self, obj: *mut T, superclass: &Class, sel: Sel) -> R
                    where T: Message {
                let msg_send_fn = msg_send_super_fn::<R>();
                let msg_send_fn: unsafe extern fn(*const Super, Sel $(, $t)*) -> R =
                    mem::transmute(msg_send_fn);
                let sup = Super { receiver: obj as *mut Object, superclass: superclass };
                let ($($a,)*) = self;
                msg_send_fn(&sup, sel $(, $a)*)
            }
        }
    );
}

message_args_impl!();
message_args_impl!(a: A);
message_args_impl!(a: A, b: B);
message_args_impl!(a: A, b: B, c: C);
message_args_impl!(a: A, b: B, c: C, d: D);
message_args_impl!(a: A, b: B, c: C, d: D, e: E);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L);

#[cfg(test)]
mod tests {
    use runtime::Object;
    use test_utils;

    #[test]
    fn test_send_message() {
        let obj = test_utils::sample_object();
        let result: *const Object = unsafe {
            msg_send![obj, self]
        };
        assert!(&*obj as *const Object == result);
    }

    #[test]
    fn test_send_message_stret() {
        let obj = test_utils::custom_object();
        let result: test_utils::CustomStruct = unsafe {
            msg_send![obj, customStruct]
        };
        let expected = test_utils::CustomStruct { a: 1, b:2, c: 3, d: 4 };
        assert!(result == expected);
    }

    #[test]
    fn test_send_message_super() {
        let obj = test_utils::custom_subclass_object();
        let superclass = test_utils::custom_class();
        unsafe {
            let _: () = msg_send![obj, setFoo:4u32];
            assert!(msg_send![super(obj, superclass), foo] == 4u32);
            // The subclass is overriden to return foo + 2
            assert!(msg_send![obj, foo] == 6u32);
        }
    }
}
<commit_msg>Added nil message tests.<commit_after>use std::marker::PhantomFn;
use std::mem;

use block::Block;
use runtime::{Class, Object, Sel, Super, self};

/*
 The Sized bound on Message is unfortunate; ideally, objc objects would not be
 treated as Sized. However, rust won't allow casting a dynamically-sized type
 pointer to an Object pointer, because dynamically-sized types can have fat
 pointers (two words) instead of real pointers.
 */
/// Types that may be sent Objective-C messages.
/// For example: objects, classes, and blocks.
pub unsafe trait Message : PhantomFn<Self> { }

unsafe impl Message for Object { }

unsafe impl Message for Class { }

unsafe impl<A, R> Message for Block<A, R> { }

#[cfg(target_arch = "x86_64")]
fn msg_send_fn<R>() -> unsafe extern fn(*mut Object, Sel, ...) -> R {
    if mem::size_of::<R>() <= 16 {
        unsafe { mem::transmute(runtime::objc_msgSend) }
    } else {
        unsafe { mem::transmute(runtime::objc_msgSend_stret) }
    }
}

#[cfg(target_arch = "x86_64")]
fn msg_send_super_fn<R>() -> unsafe extern fn(*const Super, Sel, ...) -> R {
    if mem::size_of::<R>() <= 16 {
        unsafe { mem::transmute(runtime::objc_msgSendSuper) }
    } else {
        unsafe { mem::transmute(runtime::objc_msgSendSuper_stret) }
    }
}

/// Types that may be used as the arguments of an Objective-C message.
pub trait MessageArguments {
    /// Sends a message to the given obj with the given selector and self as
    /// the arguments.
    ///
    /// The correct version of `objc_msgSend` will be chosen based on the
    /// return type. For more information, see Apple's documenation:
    /// https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/index.html#//apple_ref/doc/uid/TP40001418-CH1g-88778
    ///
    /// It is recommended to use the `msg_send!` macro rather than calling this
    /// method directly.
    unsafe fn send<T, R>(self, obj: *mut T, sel: Sel) -> R where T: Message;

    /// Sends a message to the superclass of an instance of a class with self
    /// as the arguments.
    unsafe fn send_super<T, R>(self, obj: *mut T, superclass: &Class, sel: Sel) -> R
            where T: Message;
}

macro_rules! message_args_impl {
    ($($a:ident : $t:ident),*) => (
        impl<$($t),*> MessageArguments for ($($t,)*) {
            unsafe fn send<T, R>(self, obj: *mut T, sel: Sel) -> R where T: Message {
                let msg_send_fn = msg_send_fn::<R>();
                let msg_send_fn: unsafe extern fn(*mut Object, Sel $(, $t)*) -> R =
                    mem::transmute(msg_send_fn);
                let ($($a,)*) = self;
                msg_send_fn(obj as *mut Object, sel $(, $a)*)
            }

            unsafe fn send_super<T, R>(self, obj: *mut T, superclass: &Class, sel: Sel) -> R
                    where T: Message {
                let msg_send_fn = msg_send_super_fn::<R>();
                let msg_send_fn: unsafe extern fn(*const Super, Sel $(, $t)*) -> R =
                    mem::transmute(msg_send_fn);
                let sup = Super { receiver: obj as *mut Object, superclass: superclass };
                let ($($a,)*) = self;
                msg_send_fn(&sup, sel $(, $a)*)
            }
        }
    );
}

message_args_impl!();
message_args_impl!(a: A);
message_args_impl!(a: A, b: B);
message_args_impl!(a: A, b: B, c: C);
message_args_impl!(a: A, b: B, c: C, d: D);
message_args_impl!(a: A, b: B, c: C, d: D, e: E);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L);

#[cfg(test)]
mod tests {
    use std::ptr;
    use runtime::Object;
    use test_utils;

    #[test]
    fn test_send_message() {
        let obj = test_utils::sample_object();
        let result: *const Object = unsafe {
            msg_send![obj, self]
        };
        assert!(&*obj as *const Object == result);
    }

    #[test]
    fn test_send_message_stret() {
        let obj = test_utils::custom_object();
        let result: test_utils::CustomStruct = unsafe {
            msg_send![obj, customStruct]
        };
        let expected = test_utils::CustomStruct { a: 1, b:2, c: 3, d: 4 };
        assert!(result == expected);
    }

    #[test]
    fn test_send_message_nil() {
        let nil: *mut Object = ptr::null_mut();
        let result: usize = unsafe {
            msg_send![nil, hash]
        };
        assert!(result == 0);

        let result: *mut Object = unsafe {
            msg_send![nil, description]
        };
        assert!(result.is_null());

        let result: f64 = unsafe {
            msg_send![nil, doubleValue]
        };
        assert!(result == 0.0);
    }

    #[test]
    fn test_send_message_super() {
        let obj = test_utils::custom_subclass_object();
        let superclass = test_utils::custom_class();
        unsafe {
            let _: () = msg_send![obj, setFoo:4u32];
            assert!(msg_send![super(obj, superclass), foo] == 4u32);
            // The subclass is overriden to return foo + 2
            assert!(msg_send![obj, foo] == 6u32);
        }
    }
}
<|endoftext|>


<commit_before>//! Message parsing
//!
//! Analagous to <http://netfilter.org/projects/libnetfilter_queue/doxygen/group__Parsing.html>

use libc::*;
use std::mem;
use std::ptr::null;
use std::net::Ipv4Addr;
use num::traits::PrimInt;

use error::*;
use util::*;
use ffi::*;
pub use ffi::nfqnl_msg_packet_hdr as Header;

pub trait Payload {}

pub const IPHEADER_SIZE: u16 = 160;

#[allow(dead_code)]
pub struct IPHeader {
    r1: u32,
    r2: u32,
    r3: u32,
    saddr_raw: u32,
    daddr_raw: u32
}

impl IPHeader {
    pub fn new() -> IPHeader {
        IPHeader {
            r1: 0,
            r2: 0,
            r3: 0,
            r4: 0,
            r5: 0
        }
    }

    pub fn saddr(&self) -> Ipv4Addr {
        u32_to_ipv4(&self.r4)
    }

    pub fn daddr(&self) -> Ipv4Addr {
        u32_to_ipv4(&self.r5)
    }
}

#[inline]
fn u32_to_ipv4(src: &u32) -> Ipv4Addr {
    let octets: [u8; 4] = unsafe { mem::transmute(*src) };
    Ipv4Addr::new(u8::from_be(octets[0]),
                  u8::from_be(octets[1]),
                  u8::from_be(octets[2]),
                  u8::from_be(octets[3]))
}

impl Payload for IPHeader {}

pub struct Message<'a> {
    pub raw: *mut nfgenmsg,
    pub ptr: *mut nfq_data,
    pub header: Result<&'a Header, Error>
}

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

impl<'a> Message<'a> {
    pub fn new(raw: *mut nfgenmsg, ptr: *mut nfq_data) -> Message<'a> {
        let header = unsafe {
            let ptr = nfq_get_msg_packet_hdr(ptr);
            if ptr.is_null() {
                Err(error(Reason::GetHeader, "Failed to get header", None))
            } else {
                Ok(as_ref(&ptr).unwrap())
            }
        };
        Message {
            raw: raw,
            ptr: ptr,
            header: header
        }
    }

    pub unsafe fn ip_header(&self) -> Result<&IPHeader, Error> {
        self.payload::<IPHeader>()
    }

    pub unsafe fn payload<A: Payload>(&self) -> Result<&A, Error> {
        let data: *const A = null();
        let ptr: *mut *mut A = &mut (data as *mut A);
        let _ = match nfq_get_payload(self.ptr, ptr as *mut *mut c_uchar) {
            -1 => return Err(error(Reason::GetPayload, "Failed to get payload", Some(-1))),
            _ => ()
        };
        match as_ref(&data) {
            Some(payload) => Ok(payload),
            None => Err(error(Reason::GetPayload, "Failed to get payload", None))
        }
    }
}
<commit_msg>Parse IP Header<commit_after>//! Message parsing
//!
//! Analagous to <http://netfilter.org/projects/libnetfilter_queue/doxygen/group__Parsing.html>

use libc::*;
use std::mem;
use std::ptr::null;
use std::net::Ipv4Addr;
use num::traits::PrimInt;

use error::*;
use util::*;
use ffi::*;
pub use ffi::nfqnl_msg_packet_hdr as Header;

pub trait Payload {}

pub const IPHEADER_SIZE: u16 = 160;

#[allow(dead_code)]
pub struct IPHeader {
    version_and_header_raw: u8,
    dscp_raw: u8,
    total_length_raw: u16,
    id_raw: u16,
    flags_and_offset_raw: u16,
    ttl_raw: u8,
    protocol_raw: u8,
    checksum_raw: u16,
    saddr_raw: u32,
    daddr_raw: u32
}

impl IPHeader {
    pub fn new() -> IPHeader {
        IPHeader {
            version_and_header_raw: 0,
            dscp_raw: 0,
            total_length_raw: 0,
            id_raw: 0,
            flags_and_offset_raw: 0,
            ttl_raw: 0,
            protocol_raw: 0,
            checksum_raw: 0,
            saddr_raw: 0,
            daddr_raw: 0,
        }
    }

    pub fn saddr(&self) -> Ipv4Addr {
        addr_to_ipv4(&self.saddr_raw)
    }

    pub fn daddr(&self) -> Ipv4Addr {
        addr_to_ipv4(&self.daddr_raw)
    }
}

#[inline]
fn addr_to_ipv4(src: &u32) -> Ipv4Addr {
    let octets: [u8; 4] = unsafe { mem::transmute(*src) };
    Ipv4Addr::new(u8::from_be(octets[0]),
                  u8::from_be(octets[1]),
                  u8::from_be(octets[2]),
                  u8::from_be(octets[3]))
}

impl Payload for IPHeader {}

pub struct Message<'a> {
    pub raw: *mut nfgenmsg,
    pub ptr: *mut nfq_data,
    pub header: Result<&'a Header, Error>
}

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

impl<'a> Message<'a> {
    pub fn new(raw: *mut nfgenmsg, ptr: *mut nfq_data) -> Message<'a> {
        let header = unsafe {
            let ptr = nfq_get_msg_packet_hdr(ptr);
            if ptr.is_null() {
                Err(error(Reason::GetHeader, "Failed to get header", None))
            } else {
                Ok(as_ref(&ptr).unwrap())
            }
        };
        Message {
            raw: raw,
            ptr: ptr,
            header: header
        }
    }

    pub unsafe fn ip_header(&self) -> Result<&IPHeader, Error> {
        self.payload::<IPHeader>()
    }

    pub unsafe fn payload<A: Payload>(&self) -> Result<&A, Error> {
        let data: *const A = null();
        let ptr: *mut *mut A = &mut (data as *mut A);
        let _ = match nfq_get_payload(self.ptr, ptr as *mut *mut c_uchar) {
            -1 => return Err(error(Reason::GetPayload, "Failed to get payload", Some(-1))),
            _ => ()
        };
        match as_ref(&data) {
            Some(payload) => Ok(payload),
            None => Err(error(Reason::GetPayload, "Failed to get payload", None))
        }
    }
}
<|endoftext|>