<commit_before>use geom::{vertex, Cuboid, Range, Rect, Vertex, Vertex2d, Vertex3d};
use math::{BaseNum, EuclideanSpace, Point2, Zero};
use std::ops::Deref;

/// The number of vertices in a triangle.
pub const NUM_VERTICES: u8 = 3;

/// A triangle as three vertices.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub struct Tri<V = vertex::Default>(pub [V; NUM_VERTICES as usize]);

/// An iterator yielding each of the vertices of the triangle.
#[derive(Clone, Debug)]
pub struct Vertices<V = vertex::Default> {
    tri: Tri<V>,
    index: u8,
}

/// An iterator yielding triangles whose vertices are produced by the given iterator yielding
/// vertices.
#[derive(Clone, Debug)]
pub struct IterFromVertices<I> {
    vertices: I,
}

/// An iterator that flattens an iterator yielding triangles into its vertices.
#[derive(Clone, Debug)]
pub struct VerticesFromIter<I, V = vertex::Default> {
    tris: I,
    tri: Option<Vertices<V>>,
}

impl<V> Tri<V>
where
    V: Vertex,
{
    /// Create a **Tri** by indexing into the given buffer.
    ///
    /// **Panics** if any of the given indices are out of range of the given `vertices` slice.
    pub fn from_index_tri(vertices: &[V], indices: &[usize; 3]) -> Self
    where
        V: Vertex,
    {
        from_index_tri(vertices, indices)
    }

    /// Create a **Tri** from the next three vertices yielded by the given `vertices` iterator.
    ///
    /// Returns **None** if there were not at least 3 vertices in the given iterator.
    pub fn from_vertices<I>(vertices: I) -> Option<Self>
    where
        I: IntoIterator<Item = V>,
    {
        from_vertices(vertices)
    }

    /// Produce an iterator yielding each of the vertices of the triangle.
    pub fn vertices(self) -> Vertices<V> {
        let tri = self;
        let index = 0;
        Vertices { tri, index }
    }

    /// Produce the centroid of the triangle aka the "mean"/"average" of all the points.
    pub fn centroid(self) -> V
    where
        V: EuclideanSpace,
    {
        EuclideanSpace::centroid(&self[..])
    }

    /// Maps the underlying vertices to a new type and returns the resulting `Tri`.
    pub fn map_vertices<F, V2>(self, mut map: F) -> Tri<V2>
    where
        F: FnMut(V) -> V2,
    {
        let (a, b, c) = self.into();
        Tri([map(a), map(b), map(c)])
    }
}

impl<V> Tri<V>
where
    V: Vertex2d,
{
    /// Returns `true` if the given 2D vertex is contained within the 2D `Tri`.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate nannou;
    /// # use nannou::prelude::*;
    /// # use nannou::geom::Tri;
    /// # fn main() {
    /// let a = Point2 { x: -0.5, y: 0.0 };
    /// let b = Point2 { x: 0.0, y: 1.0 };
    /// let c = Point2 { x: 0.5, y: -0.75 };
    /// let tri = Tri([a, b, c]);
    /// assert!(tri.contains(&Point2 { x: 0.0, y: 0.0 }));
    /// assert!(!tri.contains(&Point2 { x: 3.0, y: 3.0 }));
    /// # }
    /// ```
    pub fn contains(&self, v: &V) -> bool
    where
        V: Vertex2d,
    {
        let (a, b, c) = (*self).into();
        let (a, b, c) = (a.point2(), b.point2(), c.point2());
        let v = (*v).point2();

        fn sign<S>(a: Point2<S>, b: Point2<S>, c: Point2<S>) -> S
        where
            S: BaseNum,
        {
            (a[0] - c[0]) * (b[1] - c[1]) - (b[0] - c[0]) * (a[1] - c[1])
        }

        let b1 = sign(v, a, b) < V::Scalar::zero();
        let b2 = sign(v, b, c) < V::Scalar::zero();
        let b3 = sign(v, c, a) < V::Scalar::zero();

        (b1 == b2) && (b2 == b3)
    }

    /// The bounding `Rect` of the triangle.
    pub fn bounding_rect(self) -> Rect<V::Scalar>
    where
        V: Vertex2d,
    {
        let (a, b, c) = self.into();
        let (a, b, c) = (a.point2(), b.point2(), c.point2());
        let rect = Rect { x: Range::new(a.x, a.x), y: Range::new(a.y, a.y) };
        rect.stretch_to_point(b).stretch_to_point(c)
    }

    /// The bounding `Rect` of the triangle.
    pub fn bounding_cuboid(self) -> Cuboid<V::Scalar>
    where
        V: Vertex3d,
    {
        let (a, b, c) = self.into();
        let (a, b, c) = (a.point3(), b.point3(), c.point3());
        let cuboid = Cuboid {
            x: Range::new(a.x, a.x),
            y: Range::new(a.y, a.y),
            z: Range::new(a.z, a.z),
        };
        cuboid.stretch_to_point(b).stretch_to_point(c)
    }
}

/// Returns the first `Tri` that contains the given vertex.
///
/// Returns `None` if no `Tri`'s contain the given vertex.
pub fn iter_contains<I, V>(tris: I, v: &V) -> Option<I::Item>
where
    I: IntoIterator,
    I::Item: AsRef<Tri<V>>,
    V: Vertex2d,
{
    tris.into_iter().find(|tri| tri.as_ref().contains(v))
}

/// Create a **Tri** from the next three vertices yielded by the given `vertices` iterator.
///
/// Returns **None** if there were not at least 3 vertices in the given iterator.
pub fn from_vertices<I>(vertices: I) -> Option<Tri<I::Item>>
where
    I: IntoIterator,
{
    let mut vertices = vertices.into_iter();
    match (vertices.next(), vertices.next(), vertices.next()) {
        (Some(a), Some(b), Some(c)) => Some(Tri([a, b, c])),
        _ => None,
    }
}

/// Produce an iterator yielding a triangle for every three vertices yielded by the given
/// `vertices` iterator.
pub fn iter_from_vertices<I>(vertices: I) -> IterFromVertices<I::IntoIter>
where
    I: IntoIterator,
{
    let vertices = vertices.into_iter();
    IterFromVertices { vertices }
}

/// Create a **Tri** by indexing into the given buffer.
///
/// **Panics** if any of the given indices are out of range of the given `vertices` slice.
pub fn from_index_tri<V>(vertices: &[V], indices: &[usize; 3]) -> Tri<V>
where
    V: Clone,
{
    let a = vertices[indices[0]].clone();
    let b = vertices[indices[1]].clone();
    let c = vertices[indices[2]].clone();
    Tri([a, b, c])
}

/// Produce an iterator that flattens the given iterator yielding triangles into its vertices.
pub fn vertices_from_iter<I, V>(tris: I) -> VerticesFromIter<I::IntoIter, V>
where
    I: IntoIterator<Item = Tri<V>>,
{
    let tris = tris.into_iter();
    let tri = None;
    VerticesFromIter { tris, tri }
}

impl<V> Deref for Tri<V>
where
    V: Vertex,
{
    type Target = [V; 3];
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<V> From<[V; 3]> for Tri<V>
where
    V: Vertex,
{
    fn from(points: [V; 3]) -> Self {
        Tri(points)
    }
}

impl<V> From<(V, V, V)> for Tri<V>
where
    V: Vertex,
{
    fn from((a, b, c): (V, V, V)) -> Self {
        Tri([a, b, c])
    }
}

impl<V> Into<[V; 3]> for Tri<V>
where
    V: Vertex,
{
    fn into(self) -> [V; 3] {
        self.0
    }
}

impl<V> Into<(V, V, V)> for Tri<V>
where
    V: Vertex,
{
    fn into(self) -> (V, V, V) {
        (self[0], self[1], self[2])
    }
}

impl<V> AsRef<Tri<V>> for Tri<V>
where
    V: Vertex,
{
    fn as_ref(&self) -> &Tri<V> {
        self
    }
}

impl<V> AsRef<[V; 3]> for Tri<V>
where
    V: Vertex,
{
    fn as_ref(&self) -> &[V; 3] {
        &self.0
    }
}

impl<V> Iterator for Vertices<V>
where
    V: Clone,
{
    type Item = V;
    fn next(&mut self) -> Option<Self::Item> {
        if self.index < NUM_VERTICES {
            let v = self.tri.0[self.index as usize].clone();
            self.index += 1;
            Some(v)
        } else {
            None
        }
    }
}

impl<V> ExactSizeIterator for Vertices<V>
where
    V: Clone,
{
    fn len(&self) -> usize {
        NUM_VERTICES as usize - self.index as usize
    }
}

impl<I> Iterator for IterFromVertices<I>
where
    I: Iterator,
{
    type Item = Tri<I::Item>;
    fn next(&mut self) -> Option<Self::Item> {
        from_vertices(&mut self.vertices)
    }
}

impl<I, V> Iterator for VerticesFromIter<I, V>
where
    I: Iterator<Item = Tri<V>>,
    V: Vertex,
{
    type Item = V;
    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if let Some(v) = self.tri.as_mut().and_then(|vs| vs.next()) {
                return Some(v);
            }
            match self.tris.next() {
                Some(t) => self.tri = Some(t.vertices()),
                None => return None,
            }
        }
    }
}

impl<I, V> ExactSizeIterator for VerticesFromIter<I, V>
where
    I: Iterator<Item = Tri<V>> + ExactSizeIterator,
    V: Vertex,
{
    fn len(&self) -> usize {
        let current_tri_vs = self.tri.as_ref().map(|vs| vs.len()).unwrap_or(0);
        let remaining_tri_vs = self.tris.len() * NUM_VERTICES as usize;
        current_tri_vs + remaining_tri_vs
    }
}
<commit_msg>Add `geom::tri::FlattenIndices`<commit_after>use geom::{vertex, Cuboid, Range, Rect, Vertex, Vertex2d, Vertex3d};
use math::{BaseNum, EuclideanSpace, Point2, Zero};
use std::ops::Deref;

/// The number of vertices in a triangle.
pub const NUM_VERTICES: u8 = 3;

/// A triangle as three vertices.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub struct Tri<V = vertex::Default>(pub [V; NUM_VERTICES as usize]);

/// An iterator yielding each of the vertices of the triangle.
#[derive(Clone, Debug)]
pub struct Vertices<V = vertex::Default> {
    tri: Tri<V>,
    index: u8,
}

/// An iterator yielding triangles whose vertices are produced by the given iterator yielding
/// vertices.
#[derive(Clone, Debug)]
pub struct IterFromVertices<I> {
    vertices: I,
}

/// An iterator that flattens an iterator yielding triangles into its vertices.
#[derive(Clone, Debug)]
pub struct VerticesFromIter<I, V = vertex::Default> {
    tris: I,
    tri: Option<Vertices<V>>,
}

/// Converts an iterator yielding `[usize; 3]` into an iterator yielding `usize`s.
#[derive(Clone, Debug)]
pub struct FlattenIndices<I> {
    indices: I,
    b: Option<usize>,
    c: Option<usize>,
}

impl<V> Tri<V>
where
    V: Vertex,
{
    /// Create a **Tri** by indexing into the given buffer.
    ///
    /// **Panics** if any of the given indices are out of range of the given `vertices` slice.
    pub fn from_index_tri(vertices: &[V], indices: &[usize; 3]) -> Self
    where
        V: Vertex,
    {
        from_index_tri(vertices, indices)
    }

    /// Create a **Tri** from the next three vertices yielded by the given `vertices` iterator.
    ///
    /// Returns **None** if there were not at least 3 vertices in the given iterator.
    pub fn from_vertices<I>(vertices: I) -> Option<Self>
    where
        I: IntoIterator<Item = V>,
    {
        from_vertices(vertices)
    }

    /// Produce an iterator yielding each of the vertices of the triangle.
    pub fn vertices(self) -> Vertices<V> {
        let tri = self;
        let index = 0;
        Vertices { tri, index }
    }

    /// Produce the centroid of the triangle aka the "mean"/"average" of all the points.
    pub fn centroid(self) -> V
    where
        V: EuclideanSpace,
    {
        EuclideanSpace::centroid(&self[..])
    }

    /// Maps the underlying vertices to a new type and returns the resulting `Tri`.
    pub fn map_vertices<F, V2>(self, mut map: F) -> Tri<V2>
    where
        F: FnMut(V) -> V2,
    {
        let (a, b, c) = self.into();
        Tri([map(a), map(b), map(c)])
    }
}

impl<V> Tri<V>
where
    V: Vertex2d,
{
    /// Returns `true` if the given 2D vertex is contained within the 2D `Tri`.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate nannou;
    /// # use nannou::prelude::*;
    /// # use nannou::geom::Tri;
    /// # fn main() {
    /// let a = Point2 { x: -0.5, y: 0.0 };
    /// let b = Point2 { x: 0.0, y: 1.0 };
    /// let c = Point2 { x: 0.5, y: -0.75 };
    /// let tri = Tri([a, b, c]);
    /// assert!(tri.contains(&Point2 { x: 0.0, y: 0.0 }));
    /// assert!(!tri.contains(&Point2 { x: 3.0, y: 3.0 }));
    /// # }
    /// ```
    pub fn contains(&self, v: &V) -> bool
    where
        V: Vertex2d,
    {
        let (a, b, c) = (*self).into();
        let (a, b, c) = (a.point2(), b.point2(), c.point2());
        let v = (*v).point2();

        fn sign<S>(a: Point2<S>, b: Point2<S>, c: Point2<S>) -> S
        where
            S: BaseNum,
        {
            (a[0] - c[0]) * (b[1] - c[1]) - (b[0] - c[0]) * (a[1] - c[1])
        }

        let b1 = sign(v, a, b) < V::Scalar::zero();
        let b2 = sign(v, b, c) < V::Scalar::zero();
        let b3 = sign(v, c, a) < V::Scalar::zero();

        (b1 == b2) && (b2 == b3)
    }

    /// The bounding `Rect` of the triangle.
    pub fn bounding_rect(self) -> Rect<V::Scalar>
    where
        V: Vertex2d,
    {
        let (a, b, c) = self.into();
        let (a, b, c) = (a.point2(), b.point2(), c.point2());
        let rect = Rect { x: Range::new(a.x, a.x), y: Range::new(a.y, a.y) };
        rect.stretch_to_point(b).stretch_to_point(c)
    }

    /// The bounding `Rect` of the triangle.
    pub fn bounding_cuboid(self) -> Cuboid<V::Scalar>
    where
        V: Vertex3d,
    {
        let (a, b, c) = self.into();
        let (a, b, c) = (a.point3(), b.point3(), c.point3());
        let cuboid = Cuboid {
            x: Range::new(a.x, a.x),
            y: Range::new(a.y, a.y),
            z: Range::new(a.z, a.z),
        };
        cuboid.stretch_to_point(b).stretch_to_point(c)
    }
}

/// Returns the first `Tri` that contains the given vertex.
///
/// Returns `None` if no `Tri`'s contain the given vertex.
pub fn iter_contains<I, V>(tris: I, v: &V) -> Option<I::Item>
where
    I: IntoIterator,
    I::Item: AsRef<Tri<V>>,
    V: Vertex2d,
{
    tris.into_iter().find(|tri| tri.as_ref().contains(v))
}

/// Create a **Tri** from the next three vertices yielded by the given `vertices` iterator.
///
/// Returns **None** if there were not at least 3 vertices in the given iterator.
pub fn from_vertices<I>(vertices: I) -> Option<Tri<I::Item>>
where
    I: IntoIterator,
{
    let mut vertices = vertices.into_iter();
    match (vertices.next(), vertices.next(), vertices.next()) {
        (Some(a), Some(b), Some(c)) => Some(Tri([a, b, c])),
        _ => None,
    }
}

/// Produce an iterator yielding a triangle for every three vertices yielded by the given
/// `vertices` iterator.
pub fn iter_from_vertices<I>(vertices: I) -> IterFromVertices<I::IntoIter>
where
    I: IntoIterator,
{
    let vertices = vertices.into_iter();
    IterFromVertices { vertices }
}

/// Create a **Tri** by indexing into the given buffer.
///
/// **Panics** if any of the given indices are out of range of the given `vertices` slice.
pub fn from_index_tri<V>(vertices: &[V], indices: &[usize; 3]) -> Tri<V>
where
    V: Clone,
{
    let a = vertices[indices[0]].clone();
    let b = vertices[indices[1]].clone();
    let c = vertices[indices[2]].clone();
    Tri([a, b, c])
}

/// Produce an iterator that flattens the given iterator yielding triangles into its vertices.
pub fn vertices_from_iter<I, V>(tris: I) -> VerticesFromIter<I::IntoIter, V>
where
    I: IntoIterator<Item = Tri<V>>,
{
    let tris = tris.into_iter();
    let tri = None;
    VerticesFromIter { tris, tri }
}

/// Given an iterator yielding trios of indices, produce an iterator that yields each index one at
/// a time.
pub fn flatten_index_tris<I>(index_tris: I) -> FlattenIndices<I::IntoIter>
where
    I: IntoIterator<Item = [usize; 3]>,
{
    FlattenIndices {
        indices: index_tris.into_iter(),
        b: None,
        c: None,
    }
}

impl<V> Deref for Tri<V>
where
    V: Vertex,
{
    type Target = [V; 3];
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<V> From<[V; 3]> for Tri<V>
where
    V: Vertex,
{
    fn from(points: [V; 3]) -> Self {
        Tri(points)
    }
}

impl<V> From<(V, V, V)> for Tri<V>
where
    V: Vertex,
{
    fn from((a, b, c): (V, V, V)) -> Self {
        Tri([a, b, c])
    }
}

impl<V> Into<[V; 3]> for Tri<V>
where
    V: Vertex,
{
    fn into(self) -> [V; 3] {
        self.0
    }
}

impl<V> Into<(V, V, V)> for Tri<V>
where
    V: Vertex,
{
    fn into(self) -> (V, V, V) {
        (self[0], self[1], self[2])
    }
}

impl<V> AsRef<Tri<V>> for Tri<V>
where
    V: Vertex,
{
    fn as_ref(&self) -> &Tri<V> {
        self
    }
}

impl<V> AsRef<[V; 3]> for Tri<V>
where
    V: Vertex,
{
    fn as_ref(&self) -> &[V; 3] {
        &self.0
    }
}

impl<V> Iterator for Vertices<V>
where
    V: Clone,
{
    type Item = V;
    fn next(&mut self) -> Option<Self::Item> {
        if self.index < NUM_VERTICES {
            let v = self.tri.0[self.index as usize].clone();
            self.index += 1;
            Some(v)
        } else {
            None
        }
    }
}

impl<V> ExactSizeIterator for Vertices<V>
where
    V: Clone,
{
    fn len(&self) -> usize {
        NUM_VERTICES as usize - self.index as usize
    }
}

impl<I> Iterator for IterFromVertices<I>
where
    I: Iterator,
{
    type Item = Tri<I::Item>;
    fn next(&mut self) -> Option<Self::Item> {
        from_vertices(&mut self.vertices)
    }
}

impl<I, V> Iterator for VerticesFromIter<I, V>
where
    I: Iterator<Item = Tri<V>>,
    V: Vertex,
{
    type Item = V;
    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if let Some(v) = self.tri.as_mut().and_then(|vs| vs.next()) {
                return Some(v);
            }
            match self.tris.next() {
                Some(t) => self.tri = Some(t.vertices()),
                None => return None,
            }
        }
    }
}

impl<I, V> ExactSizeIterator for VerticesFromIter<I, V>
where
    I: Iterator<Item = Tri<V>> + ExactSizeIterator,
    V: Vertex,
{
    fn len(&self) -> usize {
        let current_tri_vs = self.tri.as_ref().map(|vs| vs.len()).unwrap_or(0);
        let remaining_tri_vs = self.tris.len() * NUM_VERTICES as usize;
        current_tri_vs + remaining_tri_vs
    }
}

impl<I> Iterator for FlattenIndices<I>
where
    I: Iterator<Item = [usize; 3]>,
{
    type Item = usize;
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(next) = self.b.take() {
            return Some(next);
        }
        if let Some(next) = self.c.take() {
            return Some(next);
        }
        if let Some([next, b, c]) = self.indices.next() {
            self.b = Some(b);
            self.c = Some(c);
            return Some(next);
        }
        None
    }
}

impl<I> ExactSizeIterator for FlattenIndices<I>
where
    I: Iterator<Item = [usize; 3]> + ExactSizeIterator,
{
    fn len(&self) -> usize {
        self.indices.len() * 3 + self.b.map(|_| 1).unwrap_or(0) + self.c.map(|_| 1).unwrap_or(0)
    }
}
<|endoftext|>


<commit_before><commit_msg>Better error message for debugging db opening issues<commit_after><|endoftext|>


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

//! Dissection of Ethernet (IEEE 802.3) frames.

use {
    Error,
    NamedValue,
    Protocol,
    RawBytes,
    Result,
    Val,
    ip,
    unsigned,
};

use byteorder::*;

/// The IEEE 802.3 Ethernet protocol.
pub struct Ethernet;

/// Parse a six-byte MAC address, which can be encoded as, e.g., ff:ff:ff:ff:ff:ff.
pub fn mac_address(raw: &[u8]) -> Result<Val> {
    if raw.len() != 6 {
        return Err(Error::InvalidData(format!["MAC address should have 6 B, not {}",
                                              raw.len()]));
    }

    let encoded = raw
                  .iter()
                  .map(|b| format!["{:02x}", b])
                  .collect::<Vec<String>>()
                  .join(":")
                  ;

    Ok(Val::Address { bytes: raw.to_vec(), encoded: encoded })
}

impl Protocol for Ethernet {
    fn short_name(&self) -> &str { "Ethernet" }
    fn full_name(&self) -> &str { "IEEE 802.3 Ethernet" }
    fn dissect(&self, data: &[u8]) -> Result {
        if data.len() < 14 {
            return Err(Error::Underflow { expected: 14, have: data.len(),
                message: "An Ethernet frame must be at least 14 B".to_string() })
        }

        let mut values:Vec<NamedValue> = vec![];
        values.push(("Destination".to_string(), mac_address(&data[0..6])));
        values.push(("Source".to_string(), mac_address(&data[6..12])));

        // The type/length field might be either a type or a length.
        let tlen = unsigned::<u16,NetworkEndian>(&data[12..14]);
        let remainder = &data[14..];

        match tlen {
            Ok(i) if i <= 1500 => {
                values.push(("Length".to_string(), Val::base10(i)));
            },

            Ok(i) => {
                let protocol: Box<Protocol> = match i {
                    // TODO: use the simple 'box' syntax once it hits stable
                    0x800 => Box::new(ip::IPv4),
                    0x806 => RawBytes::boxed("ARP", "Address Resolution Protocol"),
                    0x8138 => RawBytes::boxed("IPX", "Internetwork Packet Exchange"),
                    0x86dd => RawBytes::boxed("IPv6", "Internet Protocol version 6"),

                    0x9000 => Box::new(testproto::TestProtocol),

                    _ => RawBytes::unknown_protocol(&format!["0x{:x}", i]),
                };

                let protoname = protocol.short_name().to_string();
                let description = protocol.full_name().to_string();

                values.push(("Type".to_string(), Ok(Val::Enum(i as u64, protoname))));
                values.push((description, protocol.dissect(remainder)));
            },
            Err(e) => {
                values.push(("Type/length".to_string(), Err(e)));
            },
        };

        Ok(Val::Subpacket(values))
    }
}

mod testproto;
<commit_msg>Explicitly show Ethernet padding where it exists.<commit_after>/*
 * Copyright 2015-2016 Jonathan Anderson
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
 * http://opensource.org/licenses/MIT>, at your option. This file may not be
 * copied, modified, or distributed except according to those terms.
 */

//! Dissection of Ethernet (IEEE 802.3) frames.

use {
    Error,
    NamedValue,
    Protocol,
    RawBytes,
    Result,
    Val,
    ip,
    unsigned,
};

use byteorder::*;

/// The IEEE 802.3 Ethernet protocol.
pub struct Ethernet;

/// Parse a six-byte MAC address, which can be encoded as, e.g., ff:ff:ff:ff:ff:ff.
pub fn mac_address(raw: &[u8]) -> Result<Val> {
    if raw.len() != 6 {
        return Err(Error::InvalidData(format!["MAC address should have 6 B, not {}",
                                              raw.len()]));
    }

    let encoded = raw
                  .iter()
                  .map(|b| format!["{:02x}", b])
                  .collect::<Vec<String>>()
                  .join(":")
                  ;

    Ok(Val::Address { bytes: raw.to_vec(), encoded: encoded })
}

impl Protocol for Ethernet {
    fn short_name(&self) -> &str { "Ethernet" }
    fn full_name(&self) -> &str { "IEEE 802.3 Ethernet" }
    fn dissect(&self, data: &[u8]) -> Result {
        if data.len() < 14 {
            return Err(Error::Underflow { expected: 14, have: data.len(),
                message: "An Ethernet frame must be at least 14 B".to_string() })
        }

        let mut values:Vec<NamedValue> = vec![];
        values.push(("Destination".to_string(), mac_address(&data[0..6])));
        values.push(("Source".to_string(), mac_address(&data[6..12])));

        // The type/length field might be either a type or a length.
        let tlen = unsigned::<u16,NetworkEndian>(&data[12..14]);
        let remainder = &data[14..];

        match tlen {
            Ok(i) if i <= 1500 => {
                values.push(("Length".to_string(), Val::base10(i)));

                let index = i as usize;
                let packet_data = remainder[..index].to_vec();
                let padding = remainder[index..].to_vec();
                values.push(("Data".to_string(), Ok(Val::Bytes(packet_data))));
                values.push(("Padding".to_string(), Ok(Val::Bytes(padding))));
            },

            Ok(i) => {
                let protocol: Box<Protocol> = match i {
                    // TODO: use the simple 'box' syntax once it hits stable
                    0x800 => Box::new(ip::IPv4),
                    0x806 => RawBytes::boxed("ARP", "Address Resolution Protocol"),
                    0x8138 => RawBytes::boxed("IPX", "Internetwork Packet Exchange"),
                    0x86dd => RawBytes::boxed("IPv6", "Internet Protocol version 6"),

                    0x9000 => Box::new(testproto::TestProtocol),

                    _ => RawBytes::unknown_protocol(&format!["0x{:x}", i]),
                };

                let protoname = protocol.short_name().to_string();
                let description = protocol.full_name().to_string();

                values.push(("Type".to_string(), Ok(Val::Enum(i as u64, protoname))));
                values.push((description, protocol.dissect(remainder)));
            },
            Err(e) => {
                values.push(("Type/length".to_string(), Err(e)));
            },
        };

        Ok(Val::Subpacket(values))
    }
}

mod testproto;
<|endoftext|>


<commit_before>#![allow(unused_variables)]
#![cfg_attr(feature="cargo-clippy", allow(needless_pass_by_value))]

extern crate actix;
extern crate actix_web;
extern crate env_logger;
extern crate futures;
use futures::Stream;

use std::{io, env};
use actix_web::*;
use actix_web::middleware::RequestSession;
use futures::future::{FutureResult, result};

/// favicon handler
fn favicon(req: HttpRequest) -> Result<fs::NamedFile> {
    Ok(fs::NamedFile::open("../static/favicon.ico")?)
}

/// simple index handler
fn index(mut req: HttpRequest) -> Result<HttpResponse> {
    println!("{:?}", req);

    // example of ...
    if let Ok(ch) = req.poll() {
        if let futures::Async::Ready(Some(d)) = ch {
            println!("{}", String::from_utf8_lossy(d.as_ref()));
        }
    }

    // session
    let mut counter = 1;
    if let Some(count) = req.session().get::<i32>("counter")? {
        println!("SESSION value: {}", count);
        counter = count + 1;
        req.session().set("counter", counter)?;
    } else {
        req.session().set("counter", counter)?;
    }

    // html
    let html = format!(r#"<!DOCTYPE html><title>actix - basics</title><link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />

Welcome

    session counter = {}

"#, counter);

    // response
    Ok(HttpResponse::build(StatusCode::OK)
        .content_type("text/html; charset=utf-8")
        .body(&html).unwrap())

}

/// 404 handler
fn p404(req: HttpRequest) -> Result<HttpResponse> {

    // html
    let html = r#"<!DOCTYPE html><title>actix - basics</title><link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />

    back to home

404

"#;

    // response
    Ok(HttpResponse::build(StatusCode::NOT_FOUND)
        .content_type("text/html; charset=utf-8")
        .body(html).unwrap())
}

/// async handler
fn index_async(req: HttpRequest) -> FutureResult<HttpResponse, Error>
{
    println!("{:?}", req);

    result(HttpResponse::Ok()
           .content_type("text/html")
           .body(format!("Hello {}!", req.match_info().get("name").unwrap()))
           .map_err(|e| e.into()))
}

/// handler with path parameters like `/user/{name}/`
fn with_param(req: HttpRequest) -> Result<HttpResponse>
{
    println!("{:?}", req);

    Ok(HttpResponse::Ok()
       .content_type("test/plain")
       .body(format!("Hello {}!", req.match_info().get("name").unwrap()))?)
}

fn main() {
    env::set_var("RUST_LOG", "actix_web=debug");
    env::set_var("RUST_BACKTRACE", "1");
    env_logger::init();
    let sys = actix::System::new("basic-example");

    let addr = HttpServer::new(
        || Application::new()
            // enable logger
            .middleware(middleware::Logger::default())
            // cookie session middleware
            .middleware(middleware::SessionStorage::new(
                middleware::CookieSessionBackend::build(&[0; 32])
                    .secure(false)
                    .finish()
            ))
            // register favicon
            .resource("/favicon.ico", |r| r.f(favicon))
            // register simple route, handle all methods
            .resource("/index.html", |r| r.f(index))
            // with path parameters
            .resource("/user/{name}/", |r| r.method(Method::GET).f(with_param))
            // async handler
            .resource("/async/{name}", |r| r.method(Method::GET).a(index_async))
            .resource("/test", |r| r.f(|req| {
                match *req.method() {
                    Method::GET => httpcodes::HTTPOk,
                    Method::POST => httpcodes::HTTPMethodNotAllowed,
                    _ => httpcodes::HTTPNotFound,
                }
            }))
            .resource("/error.html", |r| r.f(|req| {
                error::ErrorBadRequest(io::Error::new(io::ErrorKind::Other, "test"))
            }))
            // static files
            .handler("/static/", fs::StaticFiles::new("../static/", true))
            // redirect
            .resource("/", |r| r.method(Method::GET).f(|req| {
                println!("{:?}", req);

                HttpResponse::Found()
                    .header("LOCATION", "/index.html")
                    .finish()
            }))
            // default
            .default_resource(|r| {
                r.method(Method::GET).f(p404);
                r.route().filter(pred::Not(pred::Get())).f(|req| httpcodes::HTTPMethodNotAllowed);
            }))

        .bind("127.0.0.1:8080").expect("Can not bind to 127.0.0.1:8080")
        .shutdown_timeout(0)    // <- Set shutdown timeout to 0 seconds (default 60s)
        .start();

    println!("Starting http server: 127.0.0.1:8080");
    let _ = sys.run();
}
<commit_msg>update example<commit_after>#![allow(unused_variables)]
#![cfg_attr(feature="cargo-clippy", allow(needless_pass_by_value))]

extern crate actix;
extern crate actix_web;
extern crate env_logger;
extern crate futures;
use futures::Stream;

use std::{io, env};
use actix_web::*;
use actix_web::middleware::RequestSession;
use futures::future::{FutureResult, result};

/// favicon handler
fn favicon(req: HttpRequest) -> Result<fs::NamedFile> {
    Ok(fs::NamedFile::open("../static/favicon.ico")?)
}

/// simple index handler
fn index(mut req: HttpRequest) -> Result<HttpResponse> {
    println!("{:?}", req);

    // example of ...
    if let Ok(ch) = req.poll() {
        if let futures::Async::Ready(Some(d)) = ch {
            println!("{}", String::from_utf8_lossy(d.as_ref()));
        }
    }

    // session
    let mut counter = 1;
    if let Some(count) = req.session().get::<i32>("counter")? {
        println!("SESSION value: {}", count);
        counter = count + 1;
        req.session().set("counter", counter)?;
    } else {
        req.session().set("counter", counter)?;
    }

    // html
    let html = format!(r#"<!DOCTYPE html><title>actix - basics</title><link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />

Welcome

    session counter = {}

"#, counter);

    // response
    Ok(HttpResponse::build(StatusCode::OK)
        .content_type("text/html; charset=utf-8")
        .body(&html).unwrap())

}

/// 404 handler
fn p404(req: HttpRequest) -> Result<HttpResponse> {

    // html
    let html = r#"<!DOCTYPE html><title>actix - basics</title><link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />

    back to home

404

"#;

    // response
    Ok(HttpResponse::build(StatusCode::NOT_FOUND)
        .content_type("text/html; charset=utf-8")
        .body(html).unwrap())
}

/// async handler
fn index_async(req: HttpRequest) -> FutureResult<HttpResponse, Error>
{
    println!("{:?}", req);

    result(HttpResponse::Ok()
           .content_type("text/html")
           .body(format!("Hello {}!", req.match_info().get("name").unwrap()))
           .map_err(|e| e.into()))
}

/// handler with path parameters like `/user/{name}/`
fn with_param(req: HttpRequest) -> Result<HttpResponse>
{
    println!("{:?}", req);

    Ok(HttpResponse::Ok()
       .content_type("test/plain")
       .body(format!("Hello {}!", req.match_info().get("name").unwrap()))?)
}

fn main() {
    env::set_var("RUST_LOG", "actix_web=debug");
    env::set_var("RUST_BACKTRACE", "1");
    env_logger::init();
    let sys = actix::System::new("basic-example");

    let addr = HttpServer::new(
        || Application::new()
            // enable logger
            .middleware(middleware::Logger::default())
            // cookie session middleware
            .middleware(middleware::SessionStorage::new(
                middleware::CookieSessionBackend::build(&[0; 32])
                    .secure(false)
                    .finish()
            ))
            // register favicon
            .resource("/favicon.ico", |r| r.f(favicon))
            // register simple route, handle all methods
            .resource("/index.html", |r| r.f(index))
            // with path parameters
            .resource("/user/{name}/", |r| r.method(Method::GET).f(with_param))
            // async handler
            .resource("/async/{name}", |r| r.method(Method::GET).a(index_async))
            .resource("/test", |r| r.f(|req| {
                match *req.method() {
                    Method::GET => httpcodes::HTTPOk,
                    Method::POST => httpcodes::HTTPMethodNotAllowed,
                    _ => httpcodes::HTTPNotFound,
                }
            }))
            .resource("/error.html", |r| r.f(|req| {
                error::InternalError::new(
                    io::Error::new(io::ErrorKind::Other, "test"), StatusCode::OK)
            }))
            // static files
            .handler("/static/", fs::StaticFiles::new("../static/", true))
            // redirect
            .resource("/", |r| r.method(Method::GET).f(|req| {
                println!("{:?}", req);

                HttpResponse::Found()
                    .header("LOCATION", "/index.html")
                    .finish()
            }))
            // default
            .default_resource(|r| {
                r.method(Method::GET).f(p404);
                r.route().filter(pred::Not(pred::Get())).f(|req| httpcodes::HTTPMethodNotAllowed);
            }))

        .bind("127.0.0.1:8080").expect("Can not bind to 127.0.0.1:8080")
        .shutdown_timeout(0)    // <- Set shutdown timeout to 0 seconds (default 60s)
        .start();

    println!("Starting http server: 127.0.0.1:8080");
    let _ = sys.run();
}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate rand;

use self::sdl2::Sdl;
use self::sdl2::pixels::Color;
use self::sdl2::EventPump;
use self::sdl2::event::Event;
use self::sdl2::keyboard::Keycode;
use self::sdl2::video::{Window, WindowContext};
use self::sdl2::render::{Texture, TextureCreator, WindowCanvas};
// use game_of_life::{SQUARE_SIZE, PLAYGROUND_WIDTH, PLAYGROUND_HEIGHT};

use ::domain::terrain::Terrain;

use std::time::{Duration, Instant};

use std::sync::{Mutex, Arc};
use std::thread;
use std::thread::JoinHandle;

fn test_disp() {

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

    let window : Window = video_subsystem
        .window("rust-sdl2 demo: Window", 800, 600)
        .resizable()
        .build()
        .unwrap();

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

    let mut tick = 0;

    let now = Instant::now();
    while now.elapsed().as_secs() < 1_u64 { // displays the window for 1 second

    //let mut event_pump = sdl_context.event_pump().unwrap();
        {
            // Update the window title.
            let window = canvas.window_mut();

            let position = window.position();
            let size = window.size();
            let title = format!("Window - pos({}x{}), size({}x{}): {}",
                                position.0,
                                position.1,
                                size.0,
                                size.1,
                                tick);
            window.set_title(&title).unwrap();

            tick += 1;

        }

        canvas.set_draw_color(Color::RGB(0, 0, 0));
        //canvas
        canvas.clear();
        canvas.present();
    }
}

fn initialize_windows(x_size:usize, y_size:usize, sdl_context : & Sdl) -> (WindowCanvas, Vec<u8>,  TextureCreator<WindowContext>) {

    let num_px = sdl2::pixels::PixelFormatEnum::ARGB8888.byte_size_of_pixels(x_size * y_size);

    let pixels : Vec<u8> = vec![0; num_px];

    let video_subsystem = sdl_context.video().unwrap();

    let window: Window = video_subsystem
        .window("rust-sdl2 demo: Window", 800, 600)
        //.opengl()
        .resizable()
        .build()
        .unwrap();

    let canvas: WindowCanvas = window.into_canvas().accelerated().build().unwrap();
    debug!("Using SDL_Renderer \"{}\"", canvas.info().name);
    //let mut tick = 0;
    //let mut event_pump = sdl_context.event_pump().unwrap();

    let text_creator: TextureCreator<WindowContext> = canvas.texture_creator();

    return (canvas, pixels, text_creator)
}

fn create_texture(text_creator : & TextureCreator<WindowContext>, width : usize, height : usize) -> Texture {
        text_creator.create_texture_streaming(
            sdl2::pixels::PixelFormatEnum::ARGB8888,
            width as u32,
            height as u32).unwrap()
    }

fn check_quit(event_pump : &mut EventPump) -> bool{
    for event in event_pump.poll_iter() {
        match event {
            Event::Quit { .. } |
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => return true,
            _ => false,
        };
    };

    false
}

fn update_texture(pixels :&mut Vec<u8>, terrain : &Terrain, canvas : &mut WindowCanvas, texture : &mut Texture) {
    let data = terrain.get_data_ref();
    let x_size = terrain.xsize;
    let y_size = terrain.ysize;
    let num_px = sdl2::pixels::PixelFormatEnum::ARGB8888.byte_size_of_pixels(x_size * y_size);
    assert_eq!(pixels.len() as usize, num_px);

    {
        // Update the window title.
        let window = canvas.window_mut();

        let position = window.position();
        let size = window.size();
        let title = format!("Window - pos({}x{}), size({}x{})",
                            position.0,
                            position.1,
                            size.0,
                            size.1,
                            );
        window.set_title(&title).unwrap();
    }

    // -----
    // update texture
    texture.with_lock(None, |buffer: &mut [u8], _pitch: usize| {
        for idx in 0..(x_size * y_size) {
            let offset = idx * 4;
            unsafe{
            buffer[offset + 0] = *data.get_unchecked(idx) as u8; // b
            buffer[offset + 1] = (*data.get_unchecked(idx)*100) as u8;//(data.get_unchecked(idx)*100_isize) as u8; // g
            buffer[offset + 2] = *data.get_unchecked(idx) as u8; // r
            buffer[offset + 3] = 255_u8; // a (opaque)
            }
        }
    }).unwrap();
}
//
///// this function keeps on drawing *the same* terrain over and over again.
//pub fn graph_loop(pterrain: Arc<Mutex<Terrain>>, nb_pers: usize) {
//    let xsize;
//    let ysize;
//    {
//        let terrain = pterrain.lock().unwrap();
//        xsize = terrain.xsize;
//        ysize = terrain.ysize;
//    }
//
//    let sdl_context = sdl2::init().unwrap();
//    let mut event_pump = sdl_context.event_pump()
//        .expect("Need an event pump !");
//    //initialize graphs
//    let (mut canvas,
//        mut pixels,
//        // mut texture,
//        mut text_creator) = initialize_windows(
//        xsize,
//        ysize,
//        &sdl_context);
//
//    let mut texture = create_texture(&text_creator, xsize, ysize);
//
//    // fps computation
//    let mut start = Instant::now();
//    let deltat_render = Duration::from_millis(33);
//
//    let mut exited_count: usize = 0;
//
//    'running: while exited_count < nb_pers {
//        // measure of exited count is not correct
//
//        //            // ********* GRAPH RELATED ********
//        if start.elapsed().gt(&deltat_render) {
//            //debug!("from grph exited : {}", exited_count);
//
//            // do not render more than 30 fps
//            start = Instant::now();
//            {
//                // graph update
//                let terrain = pterrain.lock().unwrap();
//                update_texture(&mut pixels, &terrain, &mut canvas, &mut texture);
//                exited_count = terrain.get_exited_cnt().clone();
//            }
//            canvas.set_draw_color(Color::RGB(0, 0, 0));
//            canvas.clear();
//            canvas.copy(&texture,
//                        None,
//                        None).unwrap();
//        }
//
//        if check_quit(&mut event_pump){
//            break 'running;
//        }
//        canvas.present();
//    }
//}
//

pub fn spawn_graph_thread(pterrain : Arc<Mutex<Terrain>>, nb_pers : usize) -> JoinHandle<()> {

    let graph_handle = thread::spawn(move || {

        let xsize;
        let ysize;
        {
            let terrain = pterrain.lock().unwrap();
            xsize = terrain.xsize;
            ysize = terrain.ysize;
        }

        let sdl_context = sdl2::init().unwrap();
        //let event_pump = sdl_context.event_pump()
        //    .expect("Need an event pump !");
        //initialize graphs
        let (mut canvas,
            mut pixels,
            // mut texture,
            text_creator) = initialize_windows(
            xsize,
            ysize,
            &sdl_context);

        let mut texture = create_texture(&text_creator, xsize, ysize);

        // fps computation
        let mut start = Instant::now();
        let deltat_render = Duration::from_millis(33);

        let mut exited_count: usize = 0;

        'running: while exited_count < nb_pers { // measure of exited count is not correct

            // ********* GRAPH RELATED ********
            if start.elapsed().gt(&deltat_render) {
                //debug!("from grph exited : {}", exited_count);
                //canvas.clear();

                {
                    // graph update
                    let terrain = pterrain.lock().unwrap();
                    update_texture(&mut pixels, &terrain, &mut canvas, &mut texture);
                    exited_count = terrain.get_exited_cnt().clone();
                }
                canvas.set_draw_color(Color::RGB(0, 0, 0));
                canvas.copy(&texture,
                            None,
                            None).unwrap();
                // do not render more than 30 fps
                start = Instant::now();
            }
            canvas.present();

        }
    });

    graph_handle
}

pub fn graph_loop(pterrain : Arc<Mutex<Terrain>>, nb_pers : usize) {

        let xsize;
        let ysize;
        {
            let terrain = pterrain.lock().unwrap();
            xsize = terrain.xsize;
            ysize = terrain.ysize;
        }

        let sdl_context = sdl2::init().unwrap();
        //let event_pump = sdl_context.event_pump()
        //    .expect("Need an event pump !");
        //initialize graphs
        let (mut canvas,
            mut pixels,
            // mut texture,
            text_creator) = initialize_windows(
            xsize,
            ysize,
            &sdl_context);

        let mut texture = create_texture(&text_creator, xsize, ysize);

        // fps computation
        let mut start = Instant::now();
        let deltat_render = Duration::from_millis(33);

        let mut exited_count: usize = 0;

        'running: while exited_count < nb_pers { // measure of exited count is not correct

            // ********* GRAPH RELATED ********
            if start.elapsed().gt(&deltat_render) {
                // do not render more than 30 fps
                start = Instant::now();

                canvas.clear();
                //println!("start {:?}",start.elapsed().subsec_nanos());

                {
                    // graph update
                    let terrain = pterrain.lock().unwrap();
                    update_texture(&mut pixels, &terrain, &mut canvas, &mut texture);
                    exited_count = terrain.get_exited_cnt().clone();

                canvas.set_draw_color(Color::RGB(0, 0, 0));
                canvas.copy(&texture,
                            None,
                            None).unwrap();
                //println!("enddraw {:?}", start.elapsed().subsec_nanos());
                }

            }
            canvas.present();
        }
}

#[cfg(test)]
mod tests {
    use graphics::*;
    use super::sdl2;
    use super::sdl2::Sdl;
    use super::sdl2::EventPump;
    use super::sdl2::event::Event;
    use super::sdl2::keyboard::Keycode;
    use super::sdl2::VideoSubsystem;
    use super::sdl2::video::{Window, WindowContext};
    use super::sdl2::render::{Canvas, WindowCanvas};

    use std::thread;
    use std::thread::JoinHandle;

// Not possible as : https://wiki.libsdl.org/CategoryThread
//    #[test]
//    fn test_failing_event_loop_thread() {
//
//        let graph_handle = thread::spawn(move || {
//            let sdl_context = sdl2::init().unwrap();
//            let mut event_pump = sdl_context.event_pump().expect("my event pump !");
//
//            let video_subsystem = sdl_context.video().unwrap();
//
//            let window: Window = video_subsystem
//                .window("rust-sdl2 demo: Window", 800, 600)
//                //.opengl()
//                .resizable()
//                .build()
//                .unwrap();
//
//            let mut canvas: WindowCanvas = window.into_canvas().accelerated().build().unwrap();
//
//            'myloop: loop {
//                canvas.present();
//
//                // This is the part that has a safety issue when ran from a thread other than main.
//                for event in event_pump.poll_iter() {
//                    match event {
//                        Event::Quit { .. } |
//                        Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'myloop,
//                        _ => (),
//                    };
//                };
//            }
//        });
//
//        graph_handle.join();
//    }

    #[test]
    fn test_win() {

        test_disp();
    }
}
<commit_msg>FIX graphics flickering by droping frames during high workload.<commit_after>extern crate sdl2;
extern crate rand;

use self::sdl2::Sdl;
use self::sdl2::pixels::Color;
use self::sdl2::EventPump;
use self::sdl2::event::Event;
use self::sdl2::keyboard::Keycode;
use self::sdl2::video::{Window, WindowContext};
use self::sdl2::render::{Texture, TextureCreator, WindowCanvas};
// use game_of_life::{SQUARE_SIZE, PLAYGROUND_WIDTH, PLAYGROUND_HEIGHT};

use ::domain::terrain::Terrain;

use std::time::{Duration, Instant};

use std::sync::{Mutex, Arc};
use std::thread;
use std::thread::JoinHandle;

fn test_disp() {

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

    let window : Window = video_subsystem
        .window("rust-sdl2 demo: Window", 800, 600)
        .resizable()
        .build()
        .unwrap();

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

    let mut tick = 0;

    let now = Instant::now();
    while now.elapsed().as_secs() < 1_u64 { // displays the window for 1 second

    //let mut event_pump = sdl_context.event_pump().unwrap();
        {
            // Update the window title.
            let window = canvas.window_mut();

            let position = window.position();
            let size = window.size();
            let title = format!("Window - pos({}x{}), size({}x{}): {}",
                                position.0,
                                position.1,
                                size.0,
                                size.1,
                                tick);
            window.set_title(&title).unwrap();

            tick += 1;

        }

        canvas.set_draw_color(Color::RGB(0, 0, 0));
        //canvas
        canvas.clear();
        canvas.present();
    }
}

fn initialize_windows(x_size:usize, y_size:usize, sdl_context : & Sdl) -> (WindowCanvas, Vec<u8>,  TextureCreator<WindowContext>) {

    let num_px = sdl2::pixels::PixelFormatEnum::ARGB8888.byte_size_of_pixels(x_size * y_size);

    let pixels : Vec<u8> = vec![0; num_px];

    let video_subsystem = sdl_context.video().unwrap();

    let window: Window = video_subsystem
        .window("rust-sdl2 demo: Window", 800, 600)
        //.opengl()
        .resizable()
        .build()
        .unwrap();

    let canvas: WindowCanvas = window.into_canvas().accelerated().build().unwrap();
    debug!("Using SDL_Renderer \"{}\"", canvas.info().name);
    //let mut tick = 0;
    //let mut event_pump = sdl_context.event_pump().unwrap();

    let text_creator: TextureCreator<WindowContext> = canvas.texture_creator();

    return (canvas, pixels, text_creator)
}

fn create_texture(text_creator : & TextureCreator<WindowContext>, width : usize, height : usize) -> Texture {
        text_creator.create_texture_streaming(
            sdl2::pixels::PixelFormatEnum::ARGB8888,
            width as u32,
            height as u32).unwrap()
    }

fn check_quit(event_pump : &mut EventPump) -> bool{
    for event in event_pump.poll_iter() {
        match event {
            Event::Quit { .. } |
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => return true,
            _ => false,
        };
    };

    false
}

fn update_texture(pixels :&mut Vec<u8>, terrain : &Terrain, canvas : &mut WindowCanvas, texture : &mut Texture) {
    let data = terrain.get_data_ref();
    let x_size = terrain.xsize;
    let y_size = terrain.ysize;
    let num_px = sdl2::pixels::PixelFormatEnum::ARGB8888.byte_size_of_pixels(x_size * y_size);
    assert_eq!(pixels.len() as usize, num_px);

    {
        // Update the window title.
        let window = canvas.window_mut();

        let position = window.position();
        let size = window.size();
        let title = format!("Window - pos({}x{}), size({}x{})",
                            position.0,
                            position.1,
                            size.0,
                            size.1,
                            );
        window.set_title(&title).unwrap();
    }

    // update texture
    texture.with_lock(None, |buffer: &mut [u8], _pitch: usize| {
        for idx in 0..(x_size * y_size) {
            let offset = idx * 4;
            unsafe{
            buffer[offset + 0] = *data.get_unchecked(idx) as u8; // b
            buffer[offset + 1] = (*data.get_unchecked(idx)*100) as u8;//(data.get_unchecked(idx)*100_isize) as u8; // g
            buffer[offset + 2] = *data.get_unchecked(idx) as u8; // r
            buffer[offset + 3] = 255_u8; // a (opaque)
            }
        }
    }).unwrap();
}

pub fn spawn_graph_thread(pterrain : Arc<Mutex<Terrain>>, nb_pers : usize) -> JoinHandle<()> {

    let graph_handle = thread::spawn(move || {

        let xsize;
        let ysize;
        {
            let terrain = pterrain.lock().unwrap();
            xsize = terrain.xsize;
            ysize = terrain.ysize;
        }

        let sdl_context = sdl2::init().unwrap();
        //let event_pump = sdl_context.event_pump()
        //    .expect("Need an event pump !");
        //initialize graphs
        let (mut canvas,
            mut pixels,
            // mut texture,
            text_creator) = initialize_windows(
            xsize,
            ysize,
            &sdl_context);

        let mut texture = create_texture(&text_creator, xsize, ysize);

        // fps computation
        let mut start = Instant::now();
        let deltat_render = Duration::from_millis(33);

        let mut exited_count: usize = 0;

        'running: while exited_count < nb_pers { // measure of exited count is not correct

            // ********* GRAPH RELATED ********
            if start.elapsed().gt(&deltat_render) {
                //debug!("from grph exited : {}", exited_count);
                //

                {
                    // graph update
                    let terrain = pterrain.lock().unwrap();
                    update_texture(&mut pixels, &terrain, &mut canvas, &mut texture);
                    exited_count = terrain.get_exited_cnt().clone();
                }
                canvas.set_draw_color(Color::RGB(0, 0, 0));
                canvas.clear();
                canvas.copy(&texture,
                            None,
                            None).unwrap();
                // do not render more than 30 fps
                start = Instant::now();
            }
            canvas.present();

        }
    });

    graph_handle
}

pub fn graph_loop(pterrain : Arc<Mutex<Terrain>>, nb_pers : usize) {

        let xsize;
        let ysize;
        {
            let terrain = pterrain.lock().unwrap();
            xsize = terrain.xsize;
            ysize = terrain.ysize;
        }

        let sdl_context = sdl2::init().unwrap();
        //let event_pump = sdl_context.event_pump()
        //    .expect("Need an event pump !");
        //initialize graphs
        let (mut canvas,
            mut pixels,
            // mut texture,
            text_creator) = initialize_windows(
            xsize,
            ysize,
            &sdl_context);

        let mut texture = create_texture(&text_creator, xsize, ysize);

        // fps computation
        let mut start = Instant::now();
        let deltat_render = Duration::from_millis(33);

        let mut exited_count: usize = 0;

        'running: while exited_count < nb_pers { // measure of exited count is not correct

            // ********* GRAPH RELATED ********
            if start.elapsed().gt(&deltat_render) {
                // do not render more than 30 fps
                start = Instant::now();

                {
                    // graph update
                    let terrain = pterrain.lock().unwrap();
                    update_texture(&mut pixels, &terrain, &mut canvas, &mut texture);
                    exited_count = terrain.get_exited_cnt();

                    canvas.set_draw_color(Color::RGB(0, 0, 0));
                    canvas.clear();

                    canvas.copy(&texture,
                            None,
                            None).unwrap();

                    canvas.present();

                    // drop frames if too long to draw
                    if start.elapsed().gt(&deltat_render){
                        start = Instant::now();
                    }
                }

            }

        }
}

#[cfg(test)]
mod tests {
    use graphics::*;
    use super::sdl2;
    use super::sdl2::Sdl;
    use super::sdl2::EventPump;
    use super::sdl2::event::Event;
    use super::sdl2::keyboard::Keycode;
    use super::sdl2::VideoSubsystem;
    use super::sdl2::video::{Window, WindowContext};
    use super::sdl2::render::{Canvas, WindowCanvas};

    use std::thread;
    use std::thread::JoinHandle;

// Not possible as : https://wiki.libsdl.org/CategoryThread
//    #[test]
//    fn test_failing_event_loop_thread() {
//
//        let graph_handle = thread::spawn(move || {
//            let sdl_context = sdl2::init().unwrap();
//            let mut event_pump = sdl_context.event_pump().expect("my event pump !");
//
//            let video_subsystem = sdl_context.video().unwrap();
//
//            let window: Window = video_subsystem
//                .window("rust-sdl2 demo: Window", 800, 600)
//                //.opengl()
//                .resizable()
//                .build()
//                .unwrap();
//
//            let mut canvas: WindowCanvas = window.into_canvas().accelerated().build().unwrap();
//
//            'myloop: loop {
//                canvas.present();
//
//                // This is the part that has a safety issue when ran from a thread other than main.
//                for event in event_pump.poll_iter() {
//                    match event {
//                        Event::Quit { .. } |
//                        Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'myloop,
//                        _ => (),
//                    };
//                };
//            }
//        });
//
//        graph_handle.join();
//    }

    #[test]
    fn test_win() {

        test_disp();
    }
}
<|endoftext|>


<commit_before>//! Defines the interface for the session-level management of HTTP/2
//! communication. This is effectively an API that allows hooking into an
//! HTTP/2 connection in order to handle events arising on the connection.
use super::{StreamId, Header};

/// A trait that defines methods that need to be defined in order to track the
/// status of a `ClientConnection`.
///
/// These methods are effectively callbacks that the `ClientConnection` invokes
/// on particular events in the HTTP/2 frame stream.
///
/// TODO Allow the session to influence the `ClientConnection` state and raise
///      errors (i.e. make the return type -> HttpResult<()>.
pub trait Session {
    /// Notifies the `Session` that a new data chunk has arrived on the
    /// connection for a particular stream. Only the raw data is passed
    /// to the callback (all padding is already discarded by the connection).
    fn new_data_chunk(&mut self, stream_id: StreamId, data: &[u8]);
    /// Notifies the `Session` that headers have arrived for a particular
    /// stream. The given list of headers is already decoded by the connection.
    fn new_headers(&mut self, stream_id: StreamId, headers: Vec<Header>);
    /// Notifies the `Session` that a particular stream got closed by the peer.
    fn end_of_stream(&mut self, stream_id: StreamId);
}

/// A trait representing a single HTTP/2 client stream. An HTTP/2 connection
/// multiplexes a number of streams.
///
/// The trait defines which operations need to be defined by a type that should
/// be useable as an HTTP/2 stream. By implementing this trait, clients can only
/// implement stream-level logic, such as how the received data should be handled,
/// instead of tracking which streams exist and what their states are.
pub trait Stream {
    /// Create a new stream with the given ID
    fn new(stream_id: StreamId) -> Self;
    /// Handle a new data chunk that has arrived for the stream.
    fn new_data_chunk(&mut self, data: &[u8]);
    /// Set headers for a stream. A stream is only allowed to have one set of
    /// headers.
    fn set_headers(&mut self, headers: Vec<Header>);
    /// Close the stream.
    fn close(&mut self);

    /// Returns the ID of the stream.
    fn id(&self) -> StreamId;
    /// Returns whether the stream is closed.
    fn is_closed(&self) -> bool;
}

/// An implementation of the `Stream` trait that saves all headers and data
/// in memory.
pub struct DefaultStream {
    /// The ID of the stream
    pub stream_id: StreamId,
    /// The headers associated with the stream (i.e. the response headers)
    pub headers: Option<Vec<Header>>,
    /// The body of the stream (i.e. the response body)
    pub body: Vec<u8>,
    /// Whether the stream is already closed
    pub closed: bool,
}

impl DefaultStream {
    /// Create a new `DefaultStream` with the given ID.
    pub fn new(stream_id: StreamId) -> DefaultStream {
        DefaultStream {
            stream_id: stream_id,
            headers: None,
            body: Vec::new(),
            closed: false,
        }
    }
}

impl Stream for DefaultStream {
    fn new(stream_id: StreamId) -> DefaultStream {
        DefaultStream::new(stream_id)
    }

    fn new_data_chunk(&mut self, data: &[u8]) {
        self.body.push_all(data);
    }

    fn set_headers(&mut self, headers: Vec<Header>) {
        self.headers = Some(headers);
    }

    fn close(&mut self) {
        self.closed = true;
    }

    fn id(&self) -> StreamId {
        self.stream_id
    }

    fn is_closed(&self) -> bool {
        self.closed
    }
}
<commit_msg>Add a DefaultSession implementation of the `Session` trait<commit_after>//! Defines the interface for the session-level management of HTTP/2
//! communication. This is effectively an API that allows hooking into an
//! HTTP/2 connection in order to handle events arising on the connection.
use std::collections::HashMap;
use super::{StreamId, Header};

/// A trait that defines methods that need to be defined in order to track the
/// status of a `ClientConnection`.
///
/// These methods are effectively callbacks that the `ClientConnection` invokes
/// on particular events in the HTTP/2 frame stream.
///
/// TODO Allow the session to influence the `ClientConnection` state and raise
///      errors (i.e. make the return type -> HttpResult<()>.
pub trait Session {
    /// Notifies the `Session` that a new data chunk has arrived on the
    /// connection for a particular stream. Only the raw data is passed
    /// to the callback (all padding is already discarded by the connection).
    fn new_data_chunk(&mut self, stream_id: StreamId, data: &[u8]);
    /// Notifies the `Session` that headers have arrived for a particular
    /// stream. The given list of headers is already decoded by the connection.
    fn new_headers(&mut self, stream_id: StreamId, headers: Vec<Header>);
    /// Notifies the `Session` that a particular stream got closed by the peer.
    fn end_of_stream(&mut self, stream_id: StreamId);
}

/// A trait representing a single HTTP/2 client stream. An HTTP/2 connection
/// multiplexes a number of streams.
///
/// The trait defines which operations need to be defined by a type that should
/// be useable as an HTTP/2 stream. By implementing this trait, clients can only
/// implement stream-level logic, such as how the received data should be handled,
/// instead of tracking which streams exist and what their states are.
pub trait Stream {
    /// Create a new stream with the given ID
    fn new(stream_id: StreamId) -> Self;
    /// Handle a new data chunk that has arrived for the stream.
    fn new_data_chunk(&mut self, data: &[u8]);
    /// Set headers for a stream. A stream is only allowed to have one set of
    /// headers.
    fn set_headers(&mut self, headers: Vec<Header>);
    /// Close the stream.
    fn close(&mut self);

    /// Returns the ID of the stream.
    fn id(&self) -> StreamId;
    /// Returns whether the stream is closed.
    fn is_closed(&self) -> bool;
}

/// An implementation of the `Stream` trait that saves all headers and data
/// in memory.
pub struct DefaultStream {
    /// The ID of the stream
    pub stream_id: StreamId,
    /// The headers associated with the stream (i.e. the response headers)
    pub headers: Option<Vec<Header>>,
    /// The body of the stream (i.e. the response body)
    pub body: Vec<u8>,
    /// Whether the stream is already closed
    pub closed: bool,
}

impl DefaultStream {
    /// Create a new `DefaultStream` with the given ID.
    pub fn new(stream_id: StreamId) -> DefaultStream {
        DefaultStream {
            stream_id: stream_id,
            headers: None,
            body: Vec::new(),
            closed: false,
        }
    }
}

impl Stream for DefaultStream {
    fn new(stream_id: StreamId) -> DefaultStream {
        DefaultStream::new(stream_id)
    }

    fn new_data_chunk(&mut self, data: &[u8]) {
        self.body.push_all(data);
    }

    fn set_headers(&mut self, headers: Vec<Header>) {
        self.headers = Some(headers);
    }

    fn close(&mut self) {
        self.closed = true;
    }

    fn id(&self) -> StreamId {
        self.stream_id
    }

    fn is_closed(&self) -> bool {
        self.closed
    }
}

/// A simple implementation of the `Session` trait.
///
/// Keeps track of which streams are currently active by holding a `HashMap`
/// of stream IDs to `Stream` instances. Callbacks delegate to the corresponding
/// stream instance, after validating the received stream ID.
///
/// The purpose of the type is to make it easier for client implementations to
/// only handle stream-level events by providing a `Stream` implementation,
/// instead of having to implement the entire session management (tracking active
/// streams, etc.).
///
/// For example, by varying the `Stream` implementation it is easy to implement
/// a client that streams responses directly into a file on the local file system,
/// instead of keeping it in memory (like the `DefaultStream` does), without
/// having to change any HTTP/2-specific logic.
pub struct DefaultSession<S=DefaultStream> where S: Stream {
    streams: HashMap<StreamId, S>,
}

impl<S> DefaultSession<S> where S: Stream {
    /// Returns a new `DefaultSession` with no active streams.
    pub fn new() -> DefaultSession<S> {
        DefaultSession {
            streams: HashMap::new(),
        }
    }

    /// Returns a reference to a stream with the given ID, if such a stream is
    /// found in the `DefaultSession`.
    pub fn get_stream(&self, stream_id: StreamId) -> Option<&S> {
        self.streams.get(&stream_id)
    }

    /// Creates a new stream with the given ID in the session.
    pub fn new_stream(&mut self, stream_id: StreamId) {
        self.streams.insert(stream_id, Stream::new(stream_id));
    }
}

impl<S> Session for DefaultSession<S> where S: Stream {
    fn new_data_chunk(&mut self, stream_id: StreamId, data: &[u8]) {
        debug!("Data chunk for stream {}", stream_id);
        let mut stream = match self.streams.get_mut(&stream_id) {
            None => {
                debug!("Received a frame for an unknown stream!");
                return;
            },
            Some(stream) => stream,
        };
        // Now let the stream handle the data chunk
        stream.new_data_chunk(data);
    }

    fn new_headers(&mut self, stream_id: StreamId, headers: Vec<Header>) {
        debug!("Headers for stream {}", stream_id);
        let mut stream = match self.streams.get_mut(&stream_id) {
            None => {
                debug!("Received a frame for an unknown stream!");
                return;
            },
            Some(stream) => stream,
        };
        // Now let the stream handle the headers
        stream.set_headers(headers);
    }

    fn end_of_stream(&mut self, stream_id: StreamId) {
        debug!("End of stream {}", stream_id);
        let mut stream = match self.streams.get_mut(&stream_id) {
            None => {
                debug!("Received a frame for an unknown stream!");
                return;
            },
            Some(stream) => stream,
        };
        stream.close()
    }
}

#[cfg(test)]
mod tests {
    use super::{
        Session, DefaultSession,
        Stream, DefaultStream,
    };

    /// Tests that a `DefaultSession` notifies the correct stream when the
    /// appropriate callback is invoked.
    ///
    /// A better unit test would give a mock Stream to the `DefaultSession`,
    /// instead of testing both the `DefaultSession` and the `DefaultStream`
    /// in the same time...
    #[test]
    fn test_default_session_notifies_stream() {
        let mut session: DefaultSession = DefaultSession::new();
        session.new_stream(1);

        // Registering some data to stream 1...
        session.new_data_chunk(1, &[1, 2, 3]);
        // ...works.
        assert_eq!(session.get_stream(1).unwrap().body, vec![1, 2, 3]);
        // Some more...
        session.new_data_chunk(1, &[4]);
        // ...works.
        assert_eq!(session.get_stream(1).unwrap().body, vec![1, 2, 3, 4]);
        // Now headers?
        let headers = vec![(b":method".to_vec(), b"GET".to_vec())];
        session.new_headers(1, headers.clone());
        assert_eq!(session.get_stream(1).unwrap().headers.clone().unwrap(),
                   headers);
        // Add another stream in the mix
        session.new_stream(3);
        // and send it some data
        session.new_data_chunk(3, &[100]);
        assert_eq!(session.get_stream(3).unwrap().body, vec![100]);
        // Finally, the stream 1 ends...
        session.end_of_stream(1);
        // ...and gets closed.
        assert!(session.get_stream(1).unwrap().closed);
        // but not the other one.
        assert!(!session.get_stream(3).unwrap().closed);
    }
}
<|endoftext|>


<commit_before>mod token;
mod error;
#[cfg(test)]
mod tests;

use std::iter::Peekable;

pub use self::token::{Token, Span};
pub use self::error::LexerError;

pub type LexerResult = Result<Token, LexerError>;

pub struct Lexer<I: Iterator> {
    reader: Peekable<I>,
    char: Option<char>,
    line: usize,
    col: usize,
    is_finished: bool,
}

impl<I: Iterator<Item=char>> Iterator for Lexer<I> {
    type Item = LexerResult;

    fn next(&mut self) -> Option<LexerResult> {
        self.read()
    }
}

impl<I: Iterator<Item=char>> Lexer<I> {
    pub fn new(reader: I) -> Lexer<I> {
        let mut l = Lexer {
            reader: reader.peekable(),
            char: None,
            line: 1,
            col: 0,
            is_finished: false,
        };
        l.bump();
        l
    }

    fn bump(&mut self) {
        self.char = self.reader.next();
        if Some('\n') == self.char {
            self.line += 1;
            self.col = 1;
        } else {
            self.col += 1;
        }
    }

    fn read(&mut self) -> Option<LexerResult> {
        self.consume_comments_and_whitespaces();
        if self.is_finished {
            None
        } else {
            self.read_next()
        }
    }

    fn read_next(&mut self) -> Option<LexerResult> {
        if let Some(c) = self.char {
            match c {
                '-' | '+' => {
                    let mut is_digit = false;
                    if let Some(nc) = self.reader.peek() {
                        is_digit = nc.is_digit(10)
                    }
                    if is_digit {
                        self.read_number()
                    } else {
                        self.read_symbol()
                    }
                },
                'a' ... 'z' | 'A' ... 'Z' |
                '/' | '*' | '%' | '>' | '<' | '=' |
                '&' => {
                    self.read_symbol()
                },
                ':' => {
                    self.read_keyword()
                },
                '0' ... '9' => {
                    self.read_number()
                },
                '"' => {
                    self.read_string()
                },
                '(' => {
                    let (line, col) = (self.line, self.col);
                    self.bump();
                    Some(Ok(t_list_start!(span!(line, col, line, col + 1))))
                },
                ')' => {
                    let (line, col) = (self.line, self.col);
                    self.bump();
                    Some(Ok(t_list_end!(span!(line, col, line, col + 1))))
                },
                '[' => {
                    let (line, col) = (self.line, self.col);
                    self.bump();
                    Some(Ok(t_vec_start!(span!(line, col, line, col + 1))))
                },
                ']' => {
                    let (line, col) = (self.line, self.col);
                    self.bump();
                    Some(Ok(t_vec_end!(span!(line, col, line, col + 1))))
                },
                '\'' => {
                    let (line, col) = (self.line, self.col);
                    self.bump();
                    Some(Ok(t_quote![span![line, col, line, col + 1]]))
                },
                '~' => {
                    let (line, col) = (self.line, self.col);
                    self.bump();
                    if Some('@') == self.char {
                        self.bump();
                        Some(Ok(t_unquote_splicing![span![line, col, line, col + 2]]))
                    } else {
                        Some(Ok(t_unquote![span![line, col, line, col + 1]]))
                    }
                },
                _ => {
                    Some(self.error())
                }
            }
        } else {
            None
        }
    }

    fn read_symbol(&mut self) -> Option<LexerResult> {
        let (line, col) = (self.line, self.col);
        let mut symbol = String::new();

        while let Some(c) = self.char {
            match c {
                '(' | ')' | '[' | ']' | ';' => {
                    break
                },
                c if c.is_whitespace() => {
                    break
                },
                _ => {
                    symbol.push(c)
                }
            }
            self.bump();
        }

        Some(Ok(t_symbol!(symbol, span!(line, col, self.line, self.col))))
    }

    fn read_keyword(&mut self) -> Option<LexerResult> {
        let (line, col) = (self.line, self.col);
        let mut keyword = String::new();

        while let Some(c) = self.char {
            match c {
                '(' | ')' | '[' | ']' | ';' => {
                    break
                },
                c if c.is_whitespace() => {
                    break
                },
                _ => {
                    keyword.push(c)
                }
            }
            self.bump();
        }

        Some(Ok(t_keyword!(keyword, span!(line, col, self.line, self.col))))
    }

    fn read_number(&mut self) -> Option<LexerResult> {
        let (line, col) = (self.line, self.col);

        let mut neg = false;
        if Some('-') == self.char {
            neg = true;
            self.bump();
        } else if Some('+') == self.char {
            self.bump();
        }

        let mut accum = 0_f64;

        while let Some(c) = self.char {
            match c {
                '0' ... '9' => {
                    accum *= 10_f64;
                    accum += c.to_digit(10).unwrap() as f64;
                    self.bump()
                },
                '.' => {
                    self.bump();

                    let mut dec = 1.0;
                    while let Some(c) = self.char {
                        match c {
                            '0' ... '9' => {
                                dec /= 10.0;
                                accum += dec * c.to_digit(10).unwrap() as f64;
                                self.bump();
                            },
                            _ => {
                                break
                            }
                        }
                    }
                },
                '(' | ')' | '[' | ']' | ';' => {
                    break
                },
                c if c.is_whitespace() => {
                    break
                },
                _ => {
                    return Some(self.error())
                }
            }
        }

        if neg {
            accum *= -1_f64;
        }

        Some(Ok(t_number!(accum, span!(line, col, self.line, self.col))))
    }

    fn read_string(&mut self) -> Option<LexerResult> {
        let (line, col) = (self.line, self.col);

        let mut res = String::new();

        self.bump();

        while let Some(c) = self.char {
            if c == '"' {
                break
            } else {
                res.push(c)
            }
            self.bump();
        }

        self.bump();

        Some(Ok(t_string!(res, span!(line, col, self.line, self.col))))
    }

    fn consume_whitespaces(&mut self) {
        while let Some(c) = self.char {
            if c.is_whitespace() {
                self.bump()
            } else {
                break
            }
        }
    }

    fn consume_comments_and_whitespaces(&mut self) {
        self.consume_whitespaces();
        while Some(';') == self.char {
            while let Some(c) = self.char {
                if c == '\n' {
                    break
                } else {
                    self.bump()
                }
            }
            self.consume_whitespaces()
        }
    }

    fn error(&mut self) -> LexerResult {
        self.is_finished = true;
        Err(LexerError::new(self.line, self.col))
    }
}
<commit_msg>Remove consume_whitespaces function<commit_after>mod token;
mod error;
#[cfg(test)]
mod tests;

use std::iter::Peekable;

pub use self::token::{Token, Span};
pub use self::error::LexerError;

pub type LexerResult = Result<Token, LexerError>;

pub struct Lexer<I: Iterator> {
    reader: Peekable<I>,
    char: Option<char>,
    line: usize,
    col: usize,
    is_finished: bool,
}

impl<I: Iterator<Item=char>> Iterator for Lexer<I> {
    type Item = LexerResult;

    fn next(&mut self) -> Option<LexerResult> {
        self.read()
    }
}

impl<I: Iterator<Item=char>> Lexer<I> {
    pub fn new(reader: I) -> Lexer<I> {
        let mut l = Lexer {
            reader: reader.peekable(),
            char: None,
            line: 1,
            col: 0,
            is_finished: false,
        };
        l.bump();
        l
    }

    fn bump(&mut self) {
        self.char = self.reader.next();
        if Some('\n') == self.char {
            self.line += 1;
            self.col = 1;
        } else {
            self.col += 1;
        }
    }

    fn read(&mut self) -> Option<LexerResult> {
        self.consume_comments_and_whitespaces();
        if self.is_finished {
            None
        } else {
            self.read_next()
        }
    }

    fn read_next(&mut self) -> Option<LexerResult> {
        if let Some(c) = self.char {
            match c {
                '-' | '+' => {
                    let mut is_digit = false;
                    if let Some(nc) = self.reader.peek() {
                        is_digit = nc.is_digit(10)
                    }
                    if is_digit {
                        self.read_number()
                    } else {
                        self.read_symbol()
                    }
                },
                'a' ... 'z' | 'A' ... 'Z' |
                '/' | '*' | '%' | '>' | '<' | '=' |
                '&' => {
                    self.read_symbol()
                },
                ':' => {
                    self.read_keyword()
                },
                '0' ... '9' => {
                    self.read_number()
                },
                '"' => {
                    self.read_string()
                },
                '(' => {
                    let (line, col) = (self.line, self.col);
                    self.bump();
                    Some(Ok(t_list_start!(span!(line, col, line, col + 1))))
                },
                ')' => {
                    let (line, col) = (self.line, self.col);
                    self.bump();
                    Some(Ok(t_list_end!(span!(line, col, line, col + 1))))
                },
                '[' => {
                    let (line, col) = (self.line, self.col);
                    self.bump();
                    Some(Ok(t_vec_start!(span!(line, col, line, col + 1))))
                },
                ']' => {
                    let (line, col) = (self.line, self.col);
                    self.bump();
                    Some(Ok(t_vec_end!(span!(line, col, line, col + 1))))
                },
                '\'' => {
                    let (line, col) = (self.line, self.col);
                    self.bump();
                    Some(Ok(t_quote![span![line, col, line, col + 1]]))
                },
                '~' => {
                    let (line, col) = (self.line, self.col);
                    self.bump();
                    if Some('@') == self.char {
                        self.bump();
                        Some(Ok(t_unquote_splicing![span![line, col, line, col + 2]]))
                    } else {
                        Some(Ok(t_unquote![span![line, col, line, col + 1]]))
                    }
                },
                _ => {
                    Some(self.error())
                }
            }
        } else {
            None
        }
    }

    fn read_symbol(&mut self) -> Option<LexerResult> {
        let (line, col) = (self.line, self.col);
        let mut symbol = String::new();

        while let Some(c) = self.char {
            match c {
                '(' | ')' | '[' | ']' | ';' => {
                    break
                },
                c if c.is_whitespace() => {
                    break
                },
                _ => {
                    symbol.push(c)
                }
            }
            self.bump();
        }

        Some(Ok(t_symbol!(symbol, span!(line, col, self.line, self.col))))
    }

    fn read_keyword(&mut self) -> Option<LexerResult> {
        let (line, col) = (self.line, self.col);
        let mut keyword = String::new();

        while let Some(c) = self.char {
            match c {
                '(' | ')' | '[' | ']' | ';' => {
                    break
                },
                c if c.is_whitespace() => {
                    break
                },
                _ => {
                    keyword.push(c)
                }
            }
            self.bump();
        }

        Some(Ok(t_keyword!(keyword, span!(line, col, self.line, self.col))))
    }

    fn read_number(&mut self) -> Option<LexerResult> {
        let (line, col) = (self.line, self.col);

        let mut neg = false;
        if Some('-') == self.char {
            neg = true;
            self.bump();
        } else if Some('+') == self.char {
            self.bump();
        }

        let mut accum = 0_f64;

        while let Some(c) = self.char {
            match c {
                '0' ... '9' => {
                    accum *= 10_f64;
                    accum += c.to_digit(10).unwrap() as f64;
                    self.bump()
                },
                '.' => {
                    self.bump();

                    let mut dec = 1.0;
                    while let Some(c) = self.char {
                        match c {
                            '0' ... '9' => {
                                dec /= 10.0;
                                accum += dec * c.to_digit(10).unwrap() as f64;
                                self.bump();
                            },
                            _ => {
                                break
                            }
                        }
                    }
                },
                '(' | ')' | '[' | ']' | ';' => {
                    break
                },
                c if c.is_whitespace() => {
                    break
                },
                _ => {
                    return Some(self.error())
                }
            }
        }

        if neg {
            accum *= -1_f64;
        }

        Some(Ok(t_number!(accum, span!(line, col, self.line, self.col))))
    }

    fn read_string(&mut self) -> Option<LexerResult> {
        let (line, col) = (self.line, self.col);

        let mut res = String::new();

        self.bump();

        while let Some(c) = self.char {
            if c == '"' {
                break
            } else {
                res.push(c)
            }
            self.bump();
        }

        self.bump();

        Some(Ok(t_string!(res, span!(line, col, self.line, self.col))))
    }

    fn consume_comments_and_whitespaces(&mut self) {
        while let Some(c) = self.char {
            match c {
                ';' => {
                    while let Some(c) = self.char {
                        if c == '\n' {
                            break
                        } else {
                            self.bump()
                        }
                    }
                },
                c if c.is_whitespace() => {
                    self.bump()
                },
                _ => {
                    break
                }
            }
        }
    }

    fn error(&mut self) -> LexerResult {
        self.is_finished = true;
        Err(LexerError::new(self.line, self.col))
    }
}
<|endoftext|>


<commit_before>#[allow(improper_ctypes)]
extern {
    fn __subscribe(driver_num: usize, subnum: usize, cb: usize);
    fn __command(driver_num: usize, cmdnum: usize, arg1: usize);
    fn __wait(a: usize, b: usize, c: usize);
}

fn command(driver_num: usize, cmdnum: usize, arg1: usize) {
    unsafe {
        __command(driver_num, cmdnum, arg1);
    }
}

fn subscribe(driver_num: usize, cmdnum: usize, callback: usize) {
    unsafe {
        __subscribe(driver_num, cmdnum, callback);
    }
}

fn wait() {
    unsafe {
        __wait(0, 0, 0);
    }
}

mod console {
    use core::prelude::*;
    use super::{command, subscribe};

    pub fn putc(c: char) {
        command(0, 0, c as usize);
    }

    pub fn puts(string: &str) {
        for c in string.chars() {
            putc(c);
        }
    }

    pub fn subscribe_read(f: fn(char)) {
        subscribe(0, 0, f as usize);
    }

}

mod gpio {
    use super::command;

    pub fn enable_pin(pin: usize) {
        command(1, 0, pin);
    }

    pub fn set_pin(pin: usize) {
        command(1, 2, pin);
    }

    pub fn clear_pin(pin: usize) {
        command(1, 3, pin);
    }

    pub fn toggle_pin(pin: usize) {
        command(1, 4, pin);
    }
}

pub mod app1 {
    use super::wait;
    use super::console::*;
    use super::gpio::*;
    use core::str;
    use core::prelude::*;

    static mut buf : [u8; 1024] = [0; 1024];
    static mut i : usize = 0;

    const WELCOME_MESSAGE: &'static str =
      "Welcome to Tock! Type \"help\" for a list of commands\r\n";

    const HELP_MESSAGE: &'static str =
r##"You may issue the following commands
  help          Prints this help message
  enable [pin]  Enables the GPIO pin
  set [pin]     Sets the GPIO pin
  clear [pin]   Clears the GPIO pin
  toggle [pin]  Toggles the GPIO pin
  echo [str]    Echos it's arguments
"##;

    const PROMPT: &'static str = "tock%> ";

    pub fn _start() {
        init();
        loop {
            wait();
        }
    }

    fn init() {
        puts(WELCOME_MESSAGE);
        subscribe_read(readc);
        puts(PROMPT);
    }

    fn readc(c: char) {
        unsafe { // referencing static variables
            match c {
                '\n' => {
                    match str::from_utf8(&buf[0..i]) {
                        Ok(cmd) => {
                          parse_command(cmd);
                        },
                        Err(_) => puts("Invalid UTF8 sequence")
                    }
                    i = 0;
                    puts(PROMPT);
                },
                '\r' => {},
                _ => {
                    if i < buf.len() {
                        buf[i] = c as u8;
                        i += 1;
                    }
                }
            }
        }
    }

    fn parse_command(line: &str) {
        use core::prelude::*;

        let mut words = line.split(|c| {
            c == '\n' || c == '\r' || c == ' ' || c == '\t'
        }).filter(|s| { !s.is_empty() });
        let cmd = words.next();
        match cmd {
            Some("help") => {
                puts(HELP_MESSAGE);
            },
            Some("echo") => {
                unsafe {
                    puts(line.slice_unchecked(5, line.len()));
                }
                puts("\r\n");
            },
            Some("enable") => {
                match words.next().map(|w| w.parse()) {
                    Some(Ok(pin)) => enable_pin(pin),
                    _ => {
                        puts("Error: first argument must be the pin number\r\n");
                    }
                }
            },
            Some("set") => {
                match words.next().map(|w| w.parse()) {
                    Some(Ok(pin)) => set_pin(pin),
                    _ => {
                        puts("Error: first argument must be the pin number\r\n");
                    }
                }
            },
            Some("clear") => {
                match words.next().map(|w| w.parse()) {
                    Some(Ok(pin)) => clear_pin(pin),
                    _ => {
                        puts("Error: first argument must be the pin number\r\n");
                    }
                }
            },
            Some("toggle") => {
                match words.next().map(|w| w.parse()) {
                    Some(Ok(pin)) => toggle_pin(pin),
                    _ => {
                        puts("Error: first argument must be the pin number\r\n");
                    }
                }
            },
            Some(c) => {
                puts("Unknown command: ");
                puts(c);
                puts("\r\n");
            },
            _ => {}
        }

    }
}

<commit_msg>test tmp006 in app<commit_after>#[allow(improper_ctypes)]
extern {
    fn __subscribe(driver_num: usize, subnum: usize, cb: usize);
    fn __command(driver_num: usize, cmdnum: usize, arg1: usize);
    fn __wait(a: usize, b: usize, c: usize);
}

fn command(driver_num: usize, cmdnum: usize, arg1: usize) {
    unsafe {
        __command(driver_num, cmdnum, arg1);
    }
}

fn subscribe(driver_num: usize, cmdnum: usize, callback: usize) {
    unsafe {
        __subscribe(driver_num, cmdnum, callback);
    }
}

fn wait() {
    unsafe {
        __wait(0, 0, 0);
    }
}

mod tmp006 {
    use super::{command, subscribe};

    pub fn enable_tmp006() {
        command(2, 0, 0);
    }

    pub fn subscribe_temperature(f: fn(i16)) {
        subscribe(2, 0, f as usize);
    }
}

mod console {
    use core::prelude::*;
    use super::{command, subscribe};

    pub fn putc(c: char) {
        command(0, 0, c as usize);
    }

    pub fn puts(string: &str) {
        for c in string.chars() {
            putc(c);
        }
    }

    pub fn subscribe_read(f: fn(char)) {
        subscribe(0, 0, f as usize);
    }

}

mod gpio {
    use super::command;

    pub fn enable_pin(pin: usize) {
        command(1, 0, pin);
    }

    pub fn set_pin(pin: usize) {
        command(1, 2, pin);
    }

    pub fn clear_pin(pin: usize) {
        command(1, 3, pin);
    }

    pub fn toggle_pin(pin: usize) {
        command(1, 4, pin);
    }
}

pub mod app1 {
    use super::wait;
    use super::console::*;
    use super::gpio::*;
    use super::tmp006::*;
    use core::str;
    use core::prelude::*;

    static mut buf : [u8; 1024] = [0; 1024];
    static mut i : usize = 0;

    const WELCOME_MESSAGE: &'static str =
      "Welcome to Tock! Type \"help\" for a list of commands\r\n";

    const HELP_MESSAGE: &'static str =
r##"You may issue the following commands
  help          Prints this help message
  enable [pin]  Enables the GPIO pin
  set [pin]     Sets the GPIO pin
  clear [pin]   Clears the GPIO pin
  toggle [pin]  Toggles the GPIO pin
  echo [str]    Echos it's arguments
"##;

    const PROMPT: &'static str = "tock%> ";

    pub fn _start() {
        init();
        loop {
            wait();
        }
    }

    fn init() {
        puts(WELCOME_MESSAGE);
        subscribe_read(readc);
        subscribe_temperature(tmp_available);
        enable_tmp006();
        puts(PROMPT);
    }

    fn tmp_available(mut tmp: i16) {
        tmp = tmp / 32;
        puts("temperature read: ");
        putc((('0' as i16) + (tmp / 10)) as u8 as char);
        putc((('0' as i16) + (tmp % 10)) as u8 as char);
        puts("\r\n");
    }

    fn readc(c: char) {
        unsafe { // referencing static variables
            match c {
                '\n' => {
                    match str::from_utf8(&buf[0..i]) {
                        Ok(cmd) => {
                          parse_command(cmd);
                        },
                        Err(_) => puts("Invalid UTF8 sequence")
                    }
                    i = 0;
                    puts(PROMPT);
                },
                '\r' => {},
                _ => {
                    if i < buf.len() {
                        buf[i] = c as u8;
                        i += 1;
                    }
                }
            }
        }
    }

    fn parse_command(line: &str) {
        use core::prelude::*;

        let mut words = line.split(|c| {
            c == '\n' || c == '\r' || c == ' ' || c == '\t'
        }).filter(|s| { !s.is_empty() });
        let cmd = words.next();
        match cmd {
            Some("help") => {
                puts(HELP_MESSAGE);
            },
            Some("echo") => {
                unsafe {
                    puts(line.slice_unchecked(5, line.len()));
                }
                puts("\r\n");
            },
            Some("enable") => {
                match words.next().map(|w| w.parse()) {
                    Some(Ok(pin)) => enable_pin(pin),
                    _ => {
                        puts("Error: first argument must be the pin number\r\n");
                    }
                }
            },
            Some("set") => {
                match words.next().map(|w| w.parse()) {
                    Some(Ok(pin)) => set_pin(pin),
                    _ => {
                        puts("Error: first argument must be the pin number\r\n");
                    }
                }
            },
            Some("clear") => {
                match words.next().map(|w| w.parse()) {
                    Some(Ok(pin)) => clear_pin(pin),
                    _ => {
                        puts("Error: first argument must be the pin number\r\n");
                    }
                }
            },
            Some("toggle") => {
                match words.next().map(|w| w.parse()) {
                    Some(Ok(pin)) => toggle_pin(pin),
                    _ => {
                        puts("Error: first argument must be the pin number\r\n");
                    }
                }
            },
            Some(c) => {
                puts("Unknown command: ");
                puts(c);
                puts("\r\n");
            },
            _ => {}
        }

    }
}

<|endoftext|>