<commit_before>use nom::error::{ErrorKind, ParseError};
use nom::{Err, IResult, Parser};

macro_rules! succ (
  (0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*));
  (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
  (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
  (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
  (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
  (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
  (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
  (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
  (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
  (9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*));
  (10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*));
  (11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*));
  (12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*));
  (13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*));
  (14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*));
  (15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*));
  (16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*));
  (17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
  (18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
  (19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
  (20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*));
  (21, $submac:ident ! ($($rest:tt)*)) => ($submac!(22, $($rest)*));
  (22, $submac:ident ! ($($rest:tt)*)) => ($submac!(23, $($rest)*));
  (23, $submac:ident ! ($($rest:tt)*)) => ($submac!(24, $($rest)*));
  (24, $submac:ident ! ($($rest:tt)*)) => ($submac!(25, $($rest)*));
  (25, $submac:ident ! ($($rest:tt)*)) => ($submac!(26, $($rest)*));
  (26, $submac:ident ! ($($rest:tt)*)) => ($submac!(27, $($rest)*));
  (27, $submac:ident ! ($($rest:tt)*)) => ($submac!(28, $($rest)*));
  (28, $submac:ident ! ($($rest:tt)*)) => ($submac!(29, $($rest)*));
  (29, $submac:ident ! ($($rest:tt)*)) => ($submac!(30, $($rest)*));
  (30, $submac:ident ! ($($rest:tt)*)) => ($submac!(31, $($rest)*));
  (31, $submac:ident ! ($($rest:tt)*)) => ($submac!(32, $($rest)*));
  (32, $submac:ident ! ($($rest:tt)*)) => ($submac!(33, $($rest)*));
  (33, $submac:ident ! ($($rest:tt)*)) => ($submac!(34, $($rest)*));
  (34, $submac:ident ! ($($rest:tt)*)) => ($submac!(35, $($rest)*));
  (35, $submac:ident ! ($($rest:tt)*)) => ($submac!(36, $($rest)*));
  (36, $submac:ident ! ($($rest:tt)*)) => ($submac!(37, $($rest)*));
  (37, $submac:ident ! ($($rest:tt)*)) => ($submac!(38, $($rest)*));
  (38, $submac:ident ! ($($rest:tt)*)) => ($submac!(39, $($rest)*));
  (39, $submac:ident ! ($($rest:tt)*)) => ($submac!(40, $($rest)*));
  (40, $submac:ident ! ($($rest:tt)*)) => ($submac!(41, $($rest)*));
);

pub(crate) trait Permutation<I, O, E> {
    fn permutation(&mut self, input: I) -> IResult<I, O, E>;
}

pub(crate) fn matroska_permutation<I: Clone, O, E: ParseError<I>, List: Permutation<I, O, E>>(
    mut l: List,
) -> impl FnMut(I) -> IResult<I, O, E> {
    move |i: I| l.permutation(i)
}

macro_rules! permutation_trait(
  (
    $name1:ident $ty1:ident $item1:ident
    $name2:ident $ty2:ident $item2:ident
    $($name3:ident $ty3:ident $item3:ident)*
  ) => (
    permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*);
  );
  (
    __impl $($name:ident $ty:ident $item:ident),+;
    $name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)*
  ) => (
    permutation_trait_impl!($($name $ty $item),+);
    permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*);
  );
  (__impl $($name:ident $ty:ident $item:ident),+;) => (
    permutation_trait_impl!($($name $ty $item),+);
  );
);

macro_rules! permutation_trait_impl(
  ($($name:ident $ty:ident $item:ident),+) => (
    impl<
      Input: Clone, $($ty),+ , Error: ParseError<Input>,
      $($name: Parser<Input, $ty, Error>),+
    > Permutation<Input, ( $($ty),+ ), Error> for ( $($name),+ ) {

      fn permutation(&mut self, mut input: Input) -> IResult<Input, ( $($ty),+ ), Error> {
        let mut res = ($(Option::<$ty>::None),+);

        loop {
          let mut err: Option<Error> = None;
          permutation_trait_inner!(0, self, input, res, err, $($name)+);

          // If we reach here, every iterator has either been applied before,
          // or errored on the remaining input
          if let Some(err) = err {
            // There are remaining parsers, and all errored on the remaining input
            return Err(Err::Error(Error::append(input, ErrorKind::Permutation, err)));
          }

          // All parsers were applied
          match res {
            ($(Some($item)),+) => return Ok((input, ($($item),+))),
            _ => unreachable!(),
          }
        }
      }
    }
  );
);

macro_rules! permutation_trait_inner(
  ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => (
    if $res.$it.is_none() {
      match $self.$it.parse($input.clone()) {
        Ok((i, o)) => {
          $input = i;
          $res.$it = Some(o);
          continue;
        }
        Err(Err::Error(e)) => {
          $err = Some(match $err {
            Some(err) => err.or(e),
            None => e,
          });
        }
        Err(e) => return Err(e),
      };
    }
    succ!($it, permutation_trait_inner!($self, $input, $res, $err, $($id)*));
  );
  ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr,) => ();
);

permutation_trait!(
  FnA A a
  FnB B b
  FnC C c
  FnD D d
  FnE E e
  FnF F f
  FnG G g
  FnH H h
  FnI I i
  FnJ J j
  FnK K k
  FnL L l
  FnM M m
  FnN N n
  FnO O o
  FnP P p
  FnQ Q q
  FnR R r
  FnS S s
  FnT T t
  FnU U u
  FnV V v
  FnW W w
  FnX X x
  FnY Y y
  FnZ Z z
  FnAA AA aa
  FnAB AB ab
  FnAC AC ac
  FnAD AD ad
  FnAE AE ae
  FnAF AF af
  FnAG AG ag
  FnAH AH ah
  FnAI AI ai
  FnAJ AJ aj
  FnAK AK ak
  FnAL AL al
  FnAM AM am
  FnAN AN an
  FnAO AO ao
);
<commit_msg>Implement a specific matroska permutation parser<commit_after>use nom::error::{ErrorKind, ParseError};
use nom::{Err, IResult, Parser};

macro_rules! succ (
  (0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*));
  (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
  (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
  (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
  (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
  (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
  (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
  (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
  (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
  (9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*));
  (10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*));
  (11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*));
  (12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*));
  (13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*));
  (14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*));
  (15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*));
  (16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*));
  (17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
  (18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
  (19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
  (20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*));
  (21, $submac:ident ! ($($rest:tt)*)) => ($submac!(22, $($rest)*));
  (22, $submac:ident ! ($($rest:tt)*)) => ($submac!(23, $($rest)*));
  (23, $submac:ident ! ($($rest:tt)*)) => ($submac!(24, $($rest)*));
  (24, $submac:ident ! ($($rest:tt)*)) => ($submac!(25, $($rest)*));
  (25, $submac:ident ! ($($rest:tt)*)) => ($submac!(26, $($rest)*));
  (26, $submac:ident ! ($($rest:tt)*)) => ($submac!(27, $($rest)*));
  (27, $submac:ident ! ($($rest:tt)*)) => ($submac!(28, $($rest)*));
  (28, $submac:ident ! ($($rest:tt)*)) => ($submac!(29, $($rest)*));
  (29, $submac:ident ! ($($rest:tt)*)) => ($submac!(30, $($rest)*));
  (30, $submac:ident ! ($($rest:tt)*)) => ($submac!(31, $($rest)*));
  (31, $submac:ident ! ($($rest:tt)*)) => ($submac!(32, $($rest)*));
  (32, $submac:ident ! ($($rest:tt)*)) => ($submac!(33, $($rest)*));
  (33, $submac:ident ! ($($rest:tt)*)) => ($submac!(34, $($rest)*));
  (34, $submac:ident ! ($($rest:tt)*)) => ($submac!(35, $($rest)*));
  (35, $submac:ident ! ($($rest:tt)*)) => ($submac!(36, $($rest)*));
  (36, $submac:ident ! ($($rest:tt)*)) => ($submac!(37, $($rest)*));
  (37, $submac:ident ! ($($rest:tt)*)) => ($submac!(38, $($rest)*));
  (38, $submac:ident ! ($($rest:tt)*)) => ($submac!(39, $($rest)*));
  (39, $submac:ident ! ($($rest:tt)*)) => ($submac!(40, $($rest)*));
  (40, $submac:ident ! ($($rest:tt)*)) => ($submac!(41, $($rest)*));
);

pub(crate) trait Permutation<'a, O, E> {
    fn permutation(&mut self, input: &'a [u8]) -> IResult<&'a [u8], O, E>;
}

pub(crate) fn matroska_permutation<'a, O, E: ParseError<&'a [u8]>, List: Permutation<'a, O, E>>(
    mut l: List,
) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], O, E> {
    move |i| l.permutation(i)
}

macro_rules! permutation_trait(
  (
    $name1:ident $ty1:ident $item1:ident
    $name2:ident $ty2:ident $item2:ident
    $($name3:ident $ty3:ident $item3:ident)*
  ) => (
    permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*);
  );
  (
    __impl $($name:ident $ty:ident $item:ident),+;
    $name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)*
  ) => (
    permutation_trait_impl!($($name $ty $item),+);
    permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*);
  );
  (__impl $($name:ident $ty:ident $item:ident),+;) => (
    permutation_trait_impl!($($name $ty $item),+);
  );
);

macro_rules! permutation_trait_impl(
  ($($name:ident $ty:ident $item:ident),+) => (
    impl<'a,
      $($ty),+ , Error: std::fmt::Debug + ParseError<&'a[u8]>,
      $($name: Parser<&'a [u8], $ty, Error>),+
    > Permutation<'a, ( $(Option<$ty>),+ ), Error> for ( $($name),+ ) {

      fn permutation(&mut self, mut input: &'a [u8]) -> IResult<&'a [u8], ( $(Option<$ty>),+ ), Error> {
        let i_ = input.clone();

        let mut res = ($(Option::<$ty>::None),+);

        // Sum of the permutation errors obtained applying each parser
        let permutation_error = loop {
          let mut err: Option<Error> = None;

          // Skip void elements
          let void_res = crate::ebml::skip_void(input);
          if let Ok((i,_)) = void_res {
            input = i;
            continue;
          }

          permutation_trait_inner!(0, self, input, res, err, $($name)+);

          // If we reach here, every iterator has either been applied before,
          // or errored on the remaining input
          // Interrupt the loop because all parsers have been applied
          break err.map(|err| Error::append(input, ErrorKind::Permutation, err));
        };

        // All parsers were applied
        if let Some(unwrapped_res) = {
            Some((
              $(
                 values!($ty, res),
              )*
            ))
        } {
            Ok((input, unwrapped_res))
        } else if let Some(e) = permutation_error {
            Err(Err::Error(e))
        } else {
            Err(Err::Error({
                nom::error::make_error(i_, nom::error::ErrorKind::Permutation)
            }))
        }
      }
    }
  );
);

macro_rules! permutation_trait_inner(
  ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => (
    if $res.$it.is_none() {
      match $self.$it.parse($input.clone()) {
        Ok((i, o)) => {
          $input = i;
          $res.$it = Some(o);
          continue;
        }
        Err(Err::Error(e)) => {
          $err = Some(match $err {
            Some(err) => err.or(e),
            None => e,
          });
        }
        Err(e) => return Err(e),
      };
    }
    succ!($it, permutation_trait_inner!($self, $input, $res, $err, $($id)*));
  );
  ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr,) => ();
);

macro_rules! values (
  (A, $tup:expr) => ($tup.0);
  (B, $tup:expr) => ($tup.1);
  (C, $tup:expr) => ($tup.2);
  (D, $tup:expr) => ($tup.3);
  (E, $tup:expr) => ($tup.4);
  (F, $tup:expr) => ($tup.5);
  (G, $tup:expr) => ($tup.6);
  (H, $tup:expr) => ($tup.7);
  (I, $tup:expr) => ($tup.8);
  (J, $tup:expr) => ($tup.9);
  (K, $tup:expr) => ($tup.10);
  (L, $tup:expr) => ($tup.11);
  (M, $tup:expr) => ($tup.12);
  (N, $tup:expr) => ($tup.13);
  (O, $tup:expr) => ($tup.14);
  (P, $tup:expr) => ($tup.15);
  (Q, $tup:expr) => ($tup.16);
  (R, $tup:expr) => ($tup.17);
  (S, $tup:expr) => ($tup.18);
  (T, $tup:expr) => ($tup.19);
  (U, $tup:expr) => ($tup.20);
  (V, $tup:expr) => ($tup.21);
  (W, $tup:expr) => ($tup.22);
  (X, $tup:expr) => ($tup.23);
  (Y, $tup:expr) => ($tup.24);
  (Z, $tup:expr) => ($tup.25);
  (AA, $tup:expr) => ($tup.26);
  (AB, $tup:expr) => ($tup.27);
  (AC, $tup:expr) => ($tup.28);
  (AD, $tup:expr) => ($tup.29);
  (AE, $tup:expr) => ($tup.30);
  (AF, $tup:expr) => ($tup.31);
  (AG, $tup:expr) => ($tup.32);
  (AH, $tup:expr) => ($tup.33);
  (AI, $tup:expr) => ($tup.34);
  (AJ, $tup:expr) => ($tup.35);
  (AK, $tup:expr) => ($tup.36);
  (AL, $tup:expr) => ($tup.37);
  (AM, $tup:expr) => ($tup.38);
  (AN, $tup:expr) => ($tup.39);
  (AO, $tup:expr) => ($tup.40);
);

permutation_trait!(
  FnA A a
  FnB B b
  FnC C c
  FnD D d
  FnE E e
  FnF F f
  FnG G g
  FnH H h
  FnI I i
  FnJ J j
  FnK K k
  FnL L l
  FnM M m
  FnN N n
  FnO O o
  FnP P p
  FnQ Q q
  FnR R r
  FnS S s
  FnT T t
  FnU U u
  FnV V v
  FnW W w
  FnX X x
  FnY Y y
  FnZ Z z
  FnAA AA aa
  FnAB AB ab
  FnAC AC ac
  FnAD AD ad
  FnAE AE ae
  FnAF AF af
  FnAG AG ag
  FnAH AH ah
  FnAI AI ai
  FnAJ AJ aj
  FnAK AK ak
  FnAL AL al
  FnAM AM am
  FnAN AN an
  FnAO AO ao
);
<|endoftext|>


<commit_before>use std::str::FromStr;
use procrs::pid::PidFile;

// FIXME: This may be better in procps
enum PidCols {
    Pid,
    Ppid
}

impl PidCols {
    fn get_file(&self) -> PidFile {
        match *self {
            PidCols::Pid => PidFile::PidStat,
            PidCols::Ppid => PidFile::PidStat,
        }
    }
    // fn get_files(cols: &[PidCols]) -> HashSet<PidCols> {
    //     let mut files = HashSet::new();
    //     for col in cols {
    //         files.insert(
    //     }
    // }
}

// Implement FromStr to allow parsing a list of columns specified by a user
impl FromStr for PidCols {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(match s {
            "pid" => PidCols::Pid,
            "ppid" => PidCols::Ppid,
            _ => return Err(()),
        })
    }
}

// Implement ToStr to get a list of columns specified by a user
// impl ToStr for PidColumns {
// }
<commit_msg>Add more columns<commit_after>use std::str::FromStr;
use std::iter::IntoIterator;
use std::collections::HashSet;
use procrs::pid::PidFile;

// FIXME: This may be better in procps
enum PidCols {
    Pid,
    Tid,
    Tgid,
    Ppid,
    RSS,
    Time,
    Cmd,
    CmdLine
}

impl PidCols {
    fn get_file(&self) -> PidFile {
        match *self {
            PidCols::Pid => PidFile::PidStat,
            PidCols::Tid => PidFile::PidStat,
            PidCols::Ppid => PidFile::PidStat,
            PidCols::Tgid => PidFile::PidStatus,
            PidCols::RSS => PidFile::PidStatus,
            PidCols::Time => PidFile::PidStatus,
            PidCols::Cmd => PidFile::PidStat,
            PidCols::CmdLine => PidFile::PidCmdline
        }
    }
}

// Implement FromStr to allow parsing a list of columns specified by a user
impl FromStr for PidCols {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(match s {
            "pid" => PidCols::Pid,
            "ppid" => PidCols::Ppid,
            _ => return Err(()),
        })
    }
}

// Implement ToStr to get a list of columns specified by a user
// impl ToStr for PidColumns {
// }
<|endoftext|>


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

use device::dev;
use a = device::attrib;

pub type MaterialHandle = int;  //placeholder
pub type VertexCount = u16;
pub type ElementCount = u16;

/// Vertex attribute descriptor, goes into the vertex shader input
#[deriving(Clone, Show)]
pub struct Attribute {
    pub buffer: super::BufferHandle, // vertex buffer to contain the data
    pub elem_count: a::Count,   // number of elements per vertex
    pub elem_type: a::Type,     // type of a single element
    pub offset: a::Offset,      // offset in bytes to the first vertex
    pub stride: a::Stride,      // stride in bytes between consecutive vertices
    pub name: String,           // a name to match the shader input
}

#[deriving(Clone, Show)]
pub enum PolygonType {
    Point,
    Line,
    LineStrip,
    TriangleList,
    TriangleStrip,
    //Quad,
}

/// Mesh descriptor, as a collection of attributes
#[deriving(Clone, Show)]
pub struct Mesh {
    pub poly_type: PolygonType,
    pub num_vertices: VertexCount,
    pub attributes: Vec<Attribute>,
}

impl Mesh {
    pub fn new(nv: VertexCount) -> Mesh {
        Mesh {
            poly_type: TriangleList,
            num_vertices: nv,
            attributes: Vec::new(),
        }
    }

    pub fn embed(&mut self, mut builder: Builder) {
        builder.finalize();
        self.attributes.push_all(builder.attributes.as_slice());
    }
}

/// The numeric type of a vertex's components.
pub enum ComponentType {
    /// An 8-bit unsigned integer component.
    U8,
    /// An 8-bit unsigned integer component normalized to `[0, 1]`.
    U8N,
    /// An 8-bit unsigned integer component that is converted to a 32-bit float
    /// at runtime by the hardware.
    U8F,
    /// An 8-bit signed integer component.
    I8,
    /// An 8-bit signed integer component normalized to `[-1, 1]`.
    I8N,
    /// An 8-bit signed integer component that is converted to a 32-bit float at
    /// runtime by the hardware.
    I8F,
    /// A 16-bit unsigned integer component.
    U16,
    /// A 16-bit unsigned integer component normalized to `[-1, 1]`.
    U16N,
    /// A 16-bit unsigned integer component that is converted to a 32-bit float
    /// at runtime by the hardware.
    U16F,
    /// A 16-bit signed integer component.
    I16,
    /// A 16-bit signed integer component normalized to `[-1, 1]`.
    I16N,
    /// A 16-bit signed integer component that is converted to a 32-bit float at
    /// runtime by the hardware.
    I16F,
    /// A 32-bit unsigned integer component.
    U32,
    /// A 32-bit unsigned integer component normalized to `[-1, 1]`.
    U32N,
    /// A 32-bit unsigned integer component that is converted to a 32-bit float
    /// at runtime by the hardware.
    U32F,
    /// A 32-bit signed integer component.
    I32,
    /// A 32-bit signed integer component normalized to `[-1, 1]`.
    I32N,
    /// A 32-bit signed integer component that is converted to a 32-bit float at
    /// runtime by the hardware.
    I32F,
    /// A 16-bit (half precision) floating point component that is converted to
    /// a 32-bit float at runtime by the hardware.
    F16,
    /// A 32-bit (single precision) floating point component.
    F32,
    /// A 64-bit (double precision) floating point componentthat is converted to
    /// a 32-bit float at runtime by the hardware.
    F64,
    /// A 64-bit (double precision) floating point component.
    F64P,
}

impl ComponentType {
    pub fn decode(&self) -> (u8, a::Type) {
        match *self {
            U8     => (1, a::Int(a::IntRaw,        a::U8,  a::Unsigned)),
            U8N    => (1, a::Int(a::IntNormalized, a::U8,  a::Unsigned)),
            U8F    => (1, a::Int(a::IntAsFloat,    a::U8,  a::Unsigned)),
            I8     => (1, a::Int(a::IntRaw,        a::U8,  a::Signed)),
            I8N    => (1, a::Int(a::IntNormalized, a::U8,  a::Signed)),
            I8F    => (1, a::Int(a::IntAsFloat,    a::U8,  a::Signed)),
            U16    => (2, a::Int(a::IntRaw,        a::U16, a::Unsigned)),
            U16N   => (2, a::Int(a::IntNormalized, a::U16, a::Unsigned)),
            U16F   => (2, a::Int(a::IntAsFloat,    a::U16, a::Unsigned)),
            I16    => (2, a::Int(a::IntRaw,        a::U16, a::Signed)),
            I16N   => (2, a::Int(a::IntNormalized, a::U16, a::Signed)),
            I16F   => (2, a::Int(a::IntAsFloat,    a::U16, a::Signed)),
            U32    => (4, a::Int(a::IntRaw,        a::U32, a::Unsigned)),
            U32N   => (4, a::Int(a::IntNormalized, a::U32, a::Unsigned)),
            U32F   => (4, a::Int(a::IntAsFloat,    a::U32, a::Unsigned)),
            I32    => (4, a::Int(a::IntRaw,        a::U32, a::Signed)),
            I32N   => (4, a::Int(a::IntNormalized, a::U32, a::Signed)),
            I32F   => (4, a::Int(a::IntAsFloat,    a::U32, a::Signed)),
            F16    => (2, a::Float(a::FloatDefault,   a::F16)),
            F32    => (4, a::Float(a::FloatDefault,   a::F32)),
            F64    => (8, a::Float(a::FloatDefault,   a::F64)),
            F64P   => (8, a::Float(a::FloatPrecision, a::F64)),
        }
    }
}

/// A helper class to populate Mesh attributes
pub struct Builder {
    buffer: super::BufferHandle,
    offset: a::Offset,
    attributes: Vec<Attribute>,
}

impl Builder {
    pub fn new(handle: super::BufferHandle) -> Builder {
        Builder {
            buffer: handle,
            offset: 0,
            attributes: Vec::new(),
        }
    }

    pub fn add(mut self, name: &str, count: a::Count, format: ComponentType) -> Builder {
        let (size, e_type) = format.decode();
        self.attributes.push(Attribute {
            buffer: self.buffer,
            elem_count: count,
            elem_type: e_type,
            offset: self.offset,
            stride: 0,
            name: name.to_string(),
        });
        self.offset += (count as a::Offset) * (size as a::Offset);
        self
    }

    fn finalize(&mut self) {
        for at in self.attributes.mut_iter() {
            at.stride = self.offset as a::Stride;
        }
    }

    pub fn complete(mut self, nv: VertexCount) -> Mesh {
        self.finalize();
        Mesh {
            poly_type: TriangleList,
            num_vertices: nv,
            attributes: self.attributes,
        }
    }
}

#[deriving(Clone, Show)]
pub enum Slice  {
    VertexSlice(VertexCount, VertexCount),
    IndexSlice(dev::Buffer, ElementCount, ElementCount),
}

/// Slice descriptor with an assigned material
#[deriving(Clone, Show)]
pub struct SubMesh {
    pub mesh: Mesh,
    pub material: MaterialHandle,
    pub slice: Slice,
}
<commit_msg>Use a type alias for the byte size<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use device::dev;
use a = device::attrib;

pub type MaterialHandle = int;  //placeholder
pub type VertexCount = u16;
pub type ElementCount = u16;

/// Vertex attribute descriptor, goes into the vertex shader input
#[deriving(Clone, Show)]
pub struct Attribute {
    pub buffer: super::BufferHandle, // vertex buffer to contain the data
    pub elem_count: a::Count,   // number of elements per vertex
    pub elem_type: a::Type,     // type of a single element
    pub offset: a::Offset,      // offset in bytes to the first vertex
    pub stride: a::Stride,      // stride in bytes between consecutive vertices
    pub name: String,           // a name to match the shader input
}

#[deriving(Clone, Show)]
pub enum PolygonType {
    Point,
    Line,
    LineStrip,
    TriangleList,
    TriangleStrip,
    //Quad,
}

/// Mesh descriptor, as a collection of attributes
#[deriving(Clone, Show)]
pub struct Mesh {
    pub poly_type: PolygonType,
    pub num_vertices: VertexCount,
    pub attributes: Vec<Attribute>,
}

impl Mesh {
    pub fn new(nv: VertexCount) -> Mesh {
        Mesh {
            poly_type: TriangleList,
            num_vertices: nv,
            attributes: Vec::new(),
        }
    }

    pub fn embed(&mut self, mut builder: Builder) {
        builder.finalize();
        self.attributes.push_all(builder.attributes.as_slice());
    }
}

/// The numeric type of a vertex's components.
pub enum ComponentType {
    /// An 8-bit unsigned integer component.
    U8,
    /// An 8-bit unsigned integer component normalized to `[0, 1]`.
    U8N,
    /// An 8-bit unsigned integer component that is converted to a 32-bit float
    /// at runtime by the hardware.
    U8F,
    /// An 8-bit signed integer component.
    I8,
    /// An 8-bit signed integer component normalized to `[-1, 1]`.
    I8N,
    /// An 8-bit signed integer component that is converted to a 32-bit float at
    /// runtime by the hardware.
    I8F,
    /// A 16-bit unsigned integer component.
    U16,
    /// A 16-bit unsigned integer component normalized to `[-1, 1]`.
    U16N,
    /// A 16-bit unsigned integer component that is converted to a 32-bit float
    /// at runtime by the hardware.
    U16F,
    /// A 16-bit signed integer component.
    I16,
    /// A 16-bit signed integer component normalized to `[-1, 1]`.
    I16N,
    /// A 16-bit signed integer component that is converted to a 32-bit float at
    /// runtime by the hardware.
    I16F,
    /// A 32-bit unsigned integer component.
    U32,
    /// A 32-bit unsigned integer component normalized to `[-1, 1]`.
    U32N,
    /// A 32-bit unsigned integer component that is converted to a 32-bit float
    /// at runtime by the hardware.
    U32F,
    /// A 32-bit signed integer component.
    I32,
    /// A 32-bit signed integer component normalized to `[-1, 1]`.
    I32N,
    /// A 32-bit signed integer component that is converted to a 32-bit float at
    /// runtime by the hardware.
    I32F,
    /// A 16-bit (half precision) floating point component that is converted to
    /// a 32-bit float at runtime by the hardware.
    F16,
    /// A 32-bit (single precision) floating point component.
    F32,
    /// A 64-bit (double precision) floating point componentthat is converted to
    /// a 32-bit float at runtime by the hardware.
    F64,
    /// A 64-bit (double precision) floating point component.
    F64P,
}

/// The number of bytes in a vertex component.
type ByteSize = u8;

impl ComponentType {
    pub fn decode(&self) -> (ByteSize, a::Type) {
        match *self {
            U8     => (1, a::Int(a::IntRaw,        a::U8,  a::Unsigned)),
            U8N    => (1, a::Int(a::IntNormalized, a::U8,  a::Unsigned)),
            U8F    => (1, a::Int(a::IntAsFloat,    a::U8,  a::Unsigned)),
            I8     => (1, a::Int(a::IntRaw,        a::U8,  a::Signed)),
            I8N    => (1, a::Int(a::IntNormalized, a::U8,  a::Signed)),
            I8F    => (1, a::Int(a::IntAsFloat,    a::U8,  a::Signed)),
            U16    => (2, a::Int(a::IntRaw,        a::U16, a::Unsigned)),
            U16N   => (2, a::Int(a::IntNormalized, a::U16, a::Unsigned)),
            U16F   => (2, a::Int(a::IntAsFloat,    a::U16, a::Unsigned)),
            I16    => (2, a::Int(a::IntRaw,        a::U16, a::Signed)),
            I16N   => (2, a::Int(a::IntNormalized, a::U16, a::Signed)),
            I16F   => (2, a::Int(a::IntAsFloat,    a::U16, a::Signed)),
            U32    => (4, a::Int(a::IntRaw,        a::U32, a::Unsigned)),
            U32N   => (4, a::Int(a::IntNormalized, a::U32, a::Unsigned)),
            U32F   => (4, a::Int(a::IntAsFloat,    a::U32, a::Unsigned)),
            I32    => (4, a::Int(a::IntRaw,        a::U32, a::Signed)),
            I32N   => (4, a::Int(a::IntNormalized, a::U32, a::Signed)),
            I32F   => (4, a::Int(a::IntAsFloat,    a::U32, a::Signed)),
            F16    => (2, a::Float(a::FloatDefault,   a::F16)),
            F32    => (4, a::Float(a::FloatDefault,   a::F32)),
            F64    => (8, a::Float(a::FloatDefault,   a::F64)),
            F64P   => (8, a::Float(a::FloatPrecision, a::F64)),
        }
    }
}

/// A helper class to populate Mesh attributes
pub struct Builder {
    buffer: super::BufferHandle,
    offset: a::Offset,
    attributes: Vec<Attribute>,
}

impl Builder {
    pub fn new(handle: super::BufferHandle) -> Builder {
        Builder {
            buffer: handle,
            offset: 0,
            attributes: Vec::new(),
        }
    }

    pub fn add(mut self, name: &str, count: a::Count, format: ComponentType) -> Builder {
        let (size, e_type) = format.decode();
        self.attributes.push(Attribute {
            buffer: self.buffer,
            elem_count: count,
            elem_type: e_type,
            offset: self.offset,
            stride: 0,
            name: name.to_string(),
        });
        self.offset += (count as a::Offset) * (size as a::Offset);
        self
    }

    fn finalize(&mut self) {
        for at in self.attributes.mut_iter() {
            at.stride = self.offset as a::Stride;
        }
    }

    pub fn complete(mut self, nv: VertexCount) -> Mesh {
        self.finalize();
        Mesh {
            poly_type: TriangleList,
            num_vertices: nv,
            attributes: self.attributes,
        }
    }
}

#[deriving(Clone, Show)]
pub enum Slice  {
    VertexSlice(VertexCount, VertexCount),
    IndexSlice(dev::Buffer, ElementCount, ElementCount),
}

/// Slice descriptor with an assigned material
#[deriving(Clone, Show)]
pub struct SubMesh {
    pub mesh: Mesh,
    pub material: MaterialHandle,
    pub slice: Slice,
}
<|endoftext|>


<commit_before>use types::{DataTy, HasDataTy};
use common::constant::VECTOR_SIZE;

use std::marker;
use std::mem;
use std::raw::Slice;
use std::iter::Iterator;

pub trait Vector<'a> : HasDataTy {
  fn size(&self) -> usize;
  fn as_array<T>(&self) -> &'a [T];
  //fn array_mut<T>(&self) -> &mut [T];
  //fn iter<T>() -> Iterator<Item=T>;
}

pub trait VRowBlock<'b> {
  fn vector(&self, column_id: usize) -> &'b Vector<'b>;
  fn set_vector(&mut self, column_id: usize, &'b Vector<'b>);
}

pub struct BorrowVRowBlock<'b> {
  vectors: Vec<&'b Vector<'b>>
}

impl<'b> VRowBlock<'b> for BorrowVRowBlock<'b> {
  fn vector(&self, column_id: usize) -> &'b Vector<'b> {
    self.vectors[column_id]
  }

  fn set_vector(&mut self, column_id: usize, vector: &'b Vector<'b>) {
    self.vectors[column_id] = vector
  }
}

pub struct ArrayVector<T> {
  array: Vec<T>,
  data_ty: DataTy
}

impl<'a, V> Vector<'a> for ArrayVector<V> {
  fn size(&self) -> usize { self.array.len() }
  fn as_array<T>(&self) -> &'a [T] {
    unsafe {
      mem::transmute(&*self.array)
    }
  }
}

impl<T> HasDataTy for ArrayVector<T> {
  fn data_ty(&self) -> &DataTy {
    &self.data_ty
  }
}

pub struct PtrVector<'a> {
  ptr: *const u8,
  size: usize,
  data_type: DataTy,
  _marker: marker::PhantomData<&'a ()>
}

impl<'a> PtrVector<'a> {
  pub fn new(ptr: *const u8, size: usize, data_type: DataTy) -> PtrVector<'a> {
    PtrVector {
      ptr: ptr,
      size: size,
      data_type: data_type,
      _marker: marker::PhantomData
    }
  }

  pub fn as_array<T>(&self) -> &[T] {
    let slice = Slice {data: self.ptr as *const T, len: VECTOR_SIZE};
    unsafe {
      mem::transmute(slice)
    }
  }

  pub fn as_mut_array<T>(&self) -> &mut [T] {
    let slice = Slice {data: self.ptr as *mut T, len: VECTOR_SIZE};
    unsafe {
      mem::transmute(slice)
    }
  }
}

impl<'a> HasDataTy for PtrVector<'a> {
  fn data_ty(&self) -> &DataTy {
    &self.data_type
  }
}<commit_msg>Rename array() to as_array() and implement as_mut_array().<commit_after>use types::{DataTy, HasDataTy};
use common::constant::VECTOR_SIZE;

use std::marker;
use std::mem;
use std::raw::Slice;
use std::iter::Iterator;

pub trait Vector<'a> : HasDataTy {
  fn size(&self) -> usize;
  unsafe fn as_array<T>(&self) -> &'a [T];
  unsafe fn as_mut_array<T>(&mut self) -> &'a mut [T];
  fn iter<T>() -> Iterator<Item=T>;
}

pub trait VRowBlock<'b> {
  fn vector(&self, column_id: usize) -> &'b Vector<'b>;
  fn set_vector(&mut self, column_id: usize, &'b Vector<'b>);
}

pub struct BorrowVRowBlock<'b> {
  vectors: Vec<&'b Vector<'b>>
}

impl<'b> VRowBlock<'b> for BorrowVRowBlock<'b> {
  fn vector(&self, column_id: usize) -> &'b Vector<'b> {
    self.vectors[column_id]
  }

  fn set_vector(&mut self, column_id: usize, vector: &'b Vector<'b>) {
    self.vectors[column_id] = vector
  }
}

pub struct ArrayVector<T> {
  array: Vec<T>,
  data_ty: DataTy
}

impl<'a, V> Vector<'a> for ArrayVector<V> {
  fn size(&self) -> usize { self.array.len() }

  unsafe fn as_array<T>(&self) -> &'a [T] {
    let slice = Slice {data: self.array.as_ptr() as *const T, len: self.array.len()};
    mem::transmute(slice)
  }

  unsafe fn as_mut_array<T>(&mut self) -> &'a mut [T] {
    let slice = Slice {data: self.array.as_mut_ptr() as *mut T, len: self.array.len()};
    unsafe {
      mem::transmute(slice)
    }
  }
}

impl<T> HasDataTy for ArrayVector<T> {
  fn data_ty(&self) -> &DataTy {
    &self.data_ty
  }
}

pub struct PtrVector<'a> {
  ptr: *const u8,
  size: usize,
  data_type: DataTy,
  _marker: marker::PhantomData<&'a ()>
}

impl<'a> PtrVector<'a> {
  pub fn new(ptr: *const u8, size: usize, data_type: DataTy) -> PtrVector<'a> {
    PtrVector {
      ptr: ptr,
      size: size,
      data_type: data_type,
      _marker: marker::PhantomData
    }
  }

  pub fn as_array<T>(&self) -> &[T] {
    let slice = Slice {data: self.ptr as *const T, len: VECTOR_SIZE};
    unsafe {
      mem::transmute(slice)
    }
  }

  pub fn as_mut_array<T>(&self) -> &mut [T] {
    let slice = Slice {data: self.ptr as *mut T, len: VECTOR_SIZE};
    unsafe {
      mem::transmute(slice)
    }
  }
}

impl<'a> HasDataTy for PtrVector<'a> {
  fn data_ty(&self) -> &DataTy {
    &self.data_type
  }
}<|endoftext|>


<commit_before>use std::io;
use std::sync::Arc;
use std::panic;

use error::ErrorCode;

use solicit::StreamId;
use error::Error;
use solicit::header::*;
use solicit::connection::EndStream;

use bytes::Bytes;

use futures;
use futures::Future;
use futures::stream;
use futures::stream::Stream;

use tokio_io::AsyncRead;
use tokio_io::AsyncWrite;
use tokio_core::net::TcpStream;
use tokio_core::reactor;
use tokio_tls::TlsAcceptorExt;

use futures_misc::*;

use solicit_async::*;
use service::Service;
use stream_part::*;
use common::*;

use server_tls::*;
use server_conf::*;

use misc::any_to_string;

struct ServerTypes;

impl Types for ServerTypes {
    type HttpStream = ServerStream;
    type HttpStreamSpecific = ServerStreamData;
    type ConnDataSpecific = ServerInnerSpecific;
    type ConnData = ServerInner;
    type ToWriteMessage = ServerToWriteMessage;

    fn first_id() -> StreamId {
        2
    }
}

pub struct ServerStreamData {
    request_handler: Option<futures::sync::mpsc::UnboundedSender<ResultOrEof<HttpStreamPart, Error>>>,
}

impl HttpStreamDataSpecific for ServerStreamData {
}

type ServerStream = HttpStreamCommon<ServerTypes>;

impl ServerStream {
    fn set_headers(&mut self, headers: Headers, last: bool) {
        if let Some(ref mut sender) = self.specific.request_handler {
            let part = HttpStreamPart {
                content: HttpStreamPartContent::Headers(headers),
                last: last,
            };
            // ignore error
            sender.send(ResultOrEof::Item(part)).ok();
        }
    }
}

impl HttpStream for ServerStream {

    type Types = ServerTypes;

    fn new_data_chunk(&mut self, data: &[u8], last: bool) {
        if let Some(ref mut sender) = self.specific.request_handler {
            let part = HttpStreamPart {
                content: HttpStreamPartContent::Data(Bytes::from(data)),
                last: last,
            };
            // ignore error
            sender.send(ResultOrEof::Item(part)).ok();
        }
    }

    fn rst(&mut self, error_code: ErrorCode) {
        if let Some(ref mut sender) = self.specific.request_handler {
            // ignore error
            sender.send(ResultOrEof::Error(Error::CodeError(error_code))).ok();
        }
    }

    fn closed_remote(&mut self) {
        if let Some(sender) = self.specific.request_handler.take() {
            // ignore error
            sender.send(ResultOrEof::Eof).ok();
        }
    }
}

struct ServerInnerSpecific {
    factory: Arc<Service>,
}

impl ConnDataSpecific for ServerInnerSpecific {
}

type ServerInner = ConnData<ServerTypes>;

impl ServerInner {
    fn new_request(&mut self, stream_id: StreamId, headers: Headers)
        -> futures::sync::mpsc::UnboundedSender<ResultOrEof<HttpStreamPart, Error>>
    {
        let (req_tx, req_rx) = futures::sync::mpsc::unbounded();

        let req_rx = req_rx.map_err(|()| Error::from(io::Error::new(io::ErrorKind::Other, "req")));
        let req_rx = stream_with_eof_and_error(req_rx, || Error::from(io::Error::new(io::ErrorKind::Other, "unexpected eof")));

        let response = panic::catch_unwind(panic::AssertUnwindSafe(|| {
            self.specific.factory.start_request(headers, HttpPartStream::new(req_rx))
        }));

        let response = response.unwrap_or_else(|e| {
            let e = any_to_string(e);
            warn!("handler panicked: {}", e);

            let headers = Headers::internal_error_500();
            Response::from_stream(stream::iter(vec![
                Ok(HttpStreamPart::intermediate_headers(headers)),
                Ok(HttpStreamPart::last_data(Bytes::from(format!("handler panicked: {}", e)))),
            ]))
        });

        let response = panic::AssertUnwindSafe(response.into_stream_flag()).catch_unwind().then(|r| {
            match r {
                Ok(r) => r,
                Err(e) => {
                    let e = any_to_string(e);
                    // TODO: send plain text error if headers weren't sent yet
                    warn!("handler panicked: {}", e);
                    Err(Error::HandlerPanicked(e))
                },
            }
        });

        {
            let to_write_tx1 = self.to_write_tx.clone();
            let to_write_tx2 = to_write_tx1.clone();

            let process_response = response.for_each(move |part: HttpStreamPart| {
                // drop error if connection is closed
                if let Err(e) = to_write_tx1.send(ServerToWriteMessage::ResponsePart(stream_id, part)) {
                    warn!("failed to write to channel, probably connection is closed: {}", e);
                }
                Ok(())
            }).then(move |r| {
                let error_code =
                    match r {
                        Ok(()) => ErrorCode::NoError,
                        Err(e) => {
                            warn!("handler stream error: {:?}", e);
                            ErrorCode::InternalError
                        }
                    };
                if let Err(e) = to_write_tx2.send(ServerToWriteMessage::ResponseStreamEnd(stream_id, error_code)) {
                    warn!("failed to write to channel, probably connection is closed: {}", e);
                }
                Ok(())
            });

            self.loop_handle.spawn(process_response);
        }

        req_tx
    }

    fn new_stream(&mut self, stream_id: StreamId, headers: Headers) -> &mut ServerStream {
        debug!("new stream: {}", stream_id);

        let req_tx = self.new_request(stream_id, headers);

        // New stream initiated by the client
        let stream = HttpStreamCommon::new(
            self.conn.peer_settings.initial_window_size,
            ServerStreamData {
                request_handler: Some(req_tx)
            });
        if let Some(..) = self.streams.map.insert(stream_id, stream) {
            panic!("inserted stream that already existed");
        }
        self.streams.map.get_mut(&stream_id).unwrap()
    }

    fn get_or_create_stream(&mut self, stream_id: StreamId, headers: Headers, last: bool) -> &mut ServerStream {
        if self.streams.get_mut(stream_id).is_some() {
            // https://github.com/rust-lang/rust/issues/36403
            let stream = self.streams.get_mut(stream_id).unwrap();
            stream.set_headers(headers, last);
            stream
        } else {
            self.new_stream(stream_id, headers)
        }
    }
}

impl ConnInner for ServerInner {
    type Types = ServerTypes;

    fn process_headers(&mut self, stream_id: StreamId, end_stream: EndStream, headers: Headers) {
        let _stream = self.get_or_create_stream(
            stream_id,
            headers,
            end_stream == EndStream::Yes);

        // TODO: drop stream if closed on both ends
    }

}

type ServerReadLoop<I> = ReadLoopData<I, ServerTypes>;
type ServerWriteLoop<I> = WriteLoopData<I, ServerTypes>;
type ServerCommandLoop = CommandLoopData<ServerTypes>;

enum ServerToWriteMessage {
    ResponsePart(StreamId, HttpStreamPart),
    // send when user provided handler completed the stream
    ResponseStreamEnd(StreamId, ErrorCode),
    Common(CommonToWriteMessage),
}

impl From<CommonToWriteMessage> for ServerToWriteMessage {
    fn from(m: CommonToWriteMessage) -> Self {
        ServerToWriteMessage::Common(m)
    }
}

enum ServerCommandMessage {
    DumpState(futures::sync::oneshot::Sender<ConnectionStateSnapshot>),
}

impl<I : AsyncWrite + Send> ServerWriteLoop<I> {
    fn _loop_handle(&self) -> reactor::Handle {
        self.inner.with(move |inner: &mut ServerInner| inner.loop_handle.clone())
    }

    fn process_response_part(self, stream_id: StreamId, part: HttpStreamPart) -> HttpFuture<Self> {
        let stream_id = self.inner.with(move |inner: &mut ServerInner| {
            let stream = inner.streams.get_mut(stream_id);
            if let Some(stream) = stream {
                if !stream.state.is_closed_local() {
                    stream.outgoing.push_back(part.content);
                    if part.last {
                        stream.outgoing_end = Some(ErrorCode::NoError);
                    }
                    Some(stream_id)
                } else {
                    None
                }
            } else {
                None
            }
        });
        if let Some(stream_id) = stream_id {
            self.send_outg_stream(stream_id)
        } else {
            Box::new(futures::finished(self))
        }
    }

    fn process_response_end(self, stream_id: StreamId, error_code: ErrorCode) -> HttpFuture<Self> {
        let stream_id = self.inner.with(move |inner: &mut ServerInner| {
            let stream = inner.streams.get_mut(stream_id);
            if let Some(stream) = stream {
                if stream.outgoing_end.is_none() {
                    stream.outgoing_end = Some(error_code);
                }
                Some(stream_id)
            } else {
                None
            }
        });
        if let Some(stream_id) = stream_id {
            self.send_outg_stream(stream_id)
        } else {
            Box::new(futures::finished(self))
        }
    }

    fn process_message(self, message: ServerToWriteMessage) -> HttpFuture<Self> {
        match message {
            ServerToWriteMessage::ResponsePart(stream_id, response) => {
                self.process_response_part(stream_id, response)
            },
            ServerToWriteMessage::ResponseStreamEnd(stream_id, error_code) => {
                self.process_response_end(stream_id, error_code)
            },
            ServerToWriteMessage::Common(common) => {
                self.process_common(common)
            },
        }
    }

    fn run(self, requests: HttpFutureStream<ServerToWriteMessage>) -> HttpFuture<()> {
        let requests = requests.map_err(Error::from);
        Box::new(requests
            .fold(self, move |wl, message: ServerToWriteMessage| {
                wl.process_message(message)
            })
            .map(|_| ()))
    }
}

impl ServerCommandLoop {
    fn process_dump_state(self, sender: futures::sync::oneshot::Sender<ConnectionStateSnapshot>) -> HttpFuture<Self> {
        // ignore send error, client might be already dead
        drop(sender.send(self.inner.with(|inner| inner.dump_state())));
        Box::new(futures::finished(self))
    }

    fn process_message(self, message: ServerCommandMessage) -> HttpFuture<Self> {
        match message {
            ServerCommandMessage::DumpState(sender) => self.process_dump_state(sender),
        }
    }

    pub fn run(self, requests: HttpFutureStreamSend<ServerCommandMessage>) -> HttpFuture<()> {
        let requests = requests.map_err(Error::from);
        Box::new(requests
            .fold(self, move |l, message: ServerCommandMessage| {
                l.process_message(message)
            })
            .map(|_| ()))
    }}

pub struct ServerConnection {
    command_tx: futures::sync::mpsc::UnboundedSender<ServerCommandMessage>,
}

impl ServerConnection {
    fn connected<F, I>(lh: &reactor::Handle, socket: HttpFutureSend<I>, _conf: ServerConf, service: Arc<F>)
                       -> (ServerConnection, HttpFuture<()>)
        where
            F : Service,
            I : AsyncRead + AsyncWrite + Send + 'static,
    {
        let lh = lh.clone();

        let (to_write_tx, to_write_rx) = futures::sync::mpsc::unbounded::<ServerToWriteMessage>();
        let (command_tx, command_rx) = futures::sync::mpsc::unbounded::<ServerCommandMessage>();

        let to_write_rx = to_write_rx.map_err(|()| Error::IoError(io::Error::new(io::ErrorKind::Other, "to_write")));
        let command_rx = Box::new(command_rx.map_err(|()| Error::IoError(io::Error::new(io::ErrorKind::Other, "command"))));

        let handshake = socket.and_then(server_handshake);

        let run = handshake.and_then(move |socket| {
            let (read, write) = socket.split();

            let inner = TaskRcMut::new(ConnData::new(
                lh,
                ServerInnerSpecific {
                    factory: service,
                },
                to_write_tx.clone()));

            let run_write = ServerWriteLoop { write: write, inner: inner.clone() }.run(Box::new(to_write_rx));
            let run_read = ServerReadLoop { read: read, inner: inner.clone() }.run();
            let run_command = ServerCommandLoop { inner: inner.clone() }.run(command_rx);

            run_write.join(run_read).join(run_command).map(|_| ())
        });

        let future = Box::new(run.then(|x| { info!("connection end: {:?}", x); x }));

        (ServerConnection {
            command_tx: command_tx,
        }, future)
    }

    pub fn new<S>(lh: &reactor::Handle, socket: TcpStream, tls: ServerTlsOption, conf: ServerConf, service: Arc<S>)
                  -> (ServerConnection, HttpFuture<()>)
        where
            S : Service,
    {
        match tls {
            ServerTlsOption::Plain =>
                ServerConnection::connected(
                    lh, Box::new(futures::finished(socket)), conf, service),
            ServerTlsOption::Tls(acceptor) =>
                ServerConnection::connected(
                    lh, Box::new(acceptor.accept_async(socket).map_err(Error::from)), conf, service),
        }
    }

    pub fn new_plain<S>(lh: &reactor::Handle, socket: TcpStream, conf: ServerConf, service: Arc<S>)
                        -> (ServerConnection, HttpFuture<()>)
        where
            S : Service,
    {
        ServerConnection::new(lh, socket, ServerTlsOption::Plain, conf, service)
    }

    pub fn new_plain_fn<F>(lh: &reactor::Handle, socket: TcpStream, conf: ServerConf, f: F)
                           -> (ServerConnection, HttpFuture<()>)
        where
            F : Fn(Headers, HttpPartStream) -> Response + Send + 'static,
    {
        struct HttpServiceFn<F>(F);

        impl<F> Service for HttpServiceFn<F>
            where F : Fn(Headers, HttpPartStream) -> Response + Send + 'static
        {
            fn start_request(&self, headers: Headers, req: HttpPartStream) -> Response {
                (self.0)(headers, req)
            }
        }

        ServerConnection::new_plain(lh, socket, conf, Arc::new(HttpServiceFn(f)))
    }

    /// For tests
    pub fn dump_state(&self) -> HttpFutureSend<ConnectionStateSnapshot> {
        let (tx, rx) = futures::oneshot();

        self.command_tx.clone().send(ServerCommandMessage::DumpState(tx))
            .expect("send request to dump state");

        let rx = rx.map_err(|_| Error::from(io::Error::new(io::ErrorKind::Other, "oneshot canceled")));

        Box::new(rx)
    }

}
<commit_msg>Rename<commit_after>use std::io;
use std::sync::Arc;
use std::panic;

use error::ErrorCode;

use solicit::StreamId;
use error::Error;
use solicit::header::*;
use solicit::connection::EndStream;

use bytes::Bytes;

use futures;
use futures::Future;
use futures::stream;
use futures::stream::Stream;

use tokio_io::AsyncRead;
use tokio_io::AsyncWrite;
use tokio_core::net::TcpStream;
use tokio_core::reactor;
use tokio_tls::TlsAcceptorExt;

use futures_misc::*;

use solicit_async::*;
use service::Service;
use stream_part::*;
use common::*;

use server_tls::*;
use server_conf::*;

use misc::any_to_string;

struct ServerTypes;

impl Types for ServerTypes {
    type HttpStream = ServerStream;
    type HttpStreamSpecific = ServerStreamData;
    type ConnDataSpecific = ServerConnData;
    type ConnData = ServerInner;
    type ToWriteMessage = ServerToWriteMessage;

    fn first_id() -> StreamId {
        2
    }
}

pub struct ServerStreamData {
    request_handler: Option<futures::sync::mpsc::UnboundedSender<ResultOrEof<HttpStreamPart, Error>>>,
}

impl HttpStreamDataSpecific for ServerStreamData {
}

type ServerStream = HttpStreamCommon<ServerTypes>;

impl ServerStream {
    fn set_headers(&mut self, headers: Headers, last: bool) {
        if let Some(ref mut sender) = self.specific.request_handler {
            let part = HttpStreamPart {
                content: HttpStreamPartContent::Headers(headers),
                last: last,
            };
            // ignore error
            sender.send(ResultOrEof::Item(part)).ok();
        }
    }
}

impl HttpStream for ServerStream {

    type Types = ServerTypes;

    fn new_data_chunk(&mut self, data: &[u8], last: bool) {
        if let Some(ref mut sender) = self.specific.request_handler {
            let part = HttpStreamPart {
                content: HttpStreamPartContent::Data(Bytes::from(data)),
                last: last,
            };
            // ignore error
            sender.send(ResultOrEof::Item(part)).ok();
        }
    }

    fn rst(&mut self, error_code: ErrorCode) {
        if let Some(ref mut sender) = self.specific.request_handler {
            // ignore error
            sender.send(ResultOrEof::Error(Error::CodeError(error_code))).ok();
        }
    }

    fn closed_remote(&mut self) {
        if let Some(sender) = self.specific.request_handler.take() {
            // ignore error
            sender.send(ResultOrEof::Eof).ok();
        }
    }
}

struct ServerConnData {
    factory: Arc<Service>,
}

impl ConnDataSpecific for ServerConnData {
}

type ServerInner = ConnData<ServerTypes>;

impl ServerInner {
    fn new_request(&mut self, stream_id: StreamId, headers: Headers)
        -> futures::sync::mpsc::UnboundedSender<ResultOrEof<HttpStreamPart, Error>>
    {
        let (req_tx, req_rx) = futures::sync::mpsc::unbounded();

        let req_rx = req_rx.map_err(|()| Error::from(io::Error::new(io::ErrorKind::Other, "req")));
        let req_rx = stream_with_eof_and_error(req_rx, || Error::from(io::Error::new(io::ErrorKind::Other, "unexpected eof")));

        let response = panic::catch_unwind(panic::AssertUnwindSafe(|| {
            self.specific.factory.start_request(headers, HttpPartStream::new(req_rx))
        }));

        let response = response.unwrap_or_else(|e| {
            let e = any_to_string(e);
            warn!("handler panicked: {}", e);

            let headers = Headers::internal_error_500();
            Response::from_stream(stream::iter(vec![
                Ok(HttpStreamPart::intermediate_headers(headers)),
                Ok(HttpStreamPart::last_data(Bytes::from(format!("handler panicked: {}", e)))),
            ]))
        });

        let response = panic::AssertUnwindSafe(response.into_stream_flag()).catch_unwind().then(|r| {
            match r {
                Ok(r) => r,
                Err(e) => {
                    let e = any_to_string(e);
                    // TODO: send plain text error if headers weren't sent yet
                    warn!("handler panicked: {}", e);
                    Err(Error::HandlerPanicked(e))
                },
            }
        });

        {
            let to_write_tx1 = self.to_write_tx.clone();
            let to_write_tx2 = to_write_tx1.clone();

            let process_response = response.for_each(move |part: HttpStreamPart| {
                // drop error if connection is closed
                if let Err(e) = to_write_tx1.send(ServerToWriteMessage::ResponsePart(stream_id, part)) {
                    warn!("failed to write to channel, probably connection is closed: {}", e);
                }
                Ok(())
            }).then(move |r| {
                let error_code =
                    match r {
                        Ok(()) => ErrorCode::NoError,
                        Err(e) => {
                            warn!("handler stream error: {:?}", e);
                            ErrorCode::InternalError
                        }
                    };
                if let Err(e) = to_write_tx2.send(ServerToWriteMessage::ResponseStreamEnd(stream_id, error_code)) {
                    warn!("failed to write to channel, probably connection is closed: {}", e);
                }
                Ok(())
            });

            self.loop_handle.spawn(process_response);
        }

        req_tx
    }

    fn new_stream(&mut self, stream_id: StreamId, headers: Headers) -> &mut ServerStream {
        debug!("new stream: {}", stream_id);

        let req_tx = self.new_request(stream_id, headers);

        // New stream initiated by the client
        let stream = HttpStreamCommon::new(
            self.conn.peer_settings.initial_window_size,
            ServerStreamData {
                request_handler: Some(req_tx)
            });
        if let Some(..) = self.streams.map.insert(stream_id, stream) {
            panic!("inserted stream that already existed");
        }
        self.streams.map.get_mut(&stream_id).unwrap()
    }

    fn get_or_create_stream(&mut self, stream_id: StreamId, headers: Headers, last: bool) -> &mut ServerStream {
        if self.streams.get_mut(stream_id).is_some() {
            // https://github.com/rust-lang/rust/issues/36403
            let stream = self.streams.get_mut(stream_id).unwrap();
            stream.set_headers(headers, last);
            stream
        } else {
            self.new_stream(stream_id, headers)
        }
    }
}

impl ConnInner for ServerInner {
    type Types = ServerTypes;

    fn process_headers(&mut self, stream_id: StreamId, end_stream: EndStream, headers: Headers) {
        let _stream = self.get_or_create_stream(
            stream_id,
            headers,
            end_stream == EndStream::Yes);

        // TODO: drop stream if closed on both ends
    }

}

type ServerReadLoop<I> = ReadLoopData<I, ServerTypes>;
type ServerWriteLoop<I> = WriteLoopData<I, ServerTypes>;
type ServerCommandLoop = CommandLoopData<ServerTypes>;

enum ServerToWriteMessage {
    ResponsePart(StreamId, HttpStreamPart),
    // send when user provided handler completed the stream
    ResponseStreamEnd(StreamId, ErrorCode),
    Common(CommonToWriteMessage),
}

impl From<CommonToWriteMessage> for ServerToWriteMessage {
    fn from(m: CommonToWriteMessage) -> Self {
        ServerToWriteMessage::Common(m)
    }
}

enum ServerCommandMessage {
    DumpState(futures::sync::oneshot::Sender<ConnectionStateSnapshot>),
}

impl<I : AsyncWrite + Send> ServerWriteLoop<I> {
    fn _loop_handle(&self) -> reactor::Handle {
        self.inner.with(move |inner: &mut ServerInner| inner.loop_handle.clone())
    }

    fn process_response_part(self, stream_id: StreamId, part: HttpStreamPart) -> HttpFuture<Self> {
        let stream_id = self.inner.with(move |inner: &mut ServerInner| {
            let stream = inner.streams.get_mut(stream_id);
            if let Some(stream) = stream {
                if !stream.state.is_closed_local() {
                    stream.outgoing.push_back(part.content);
                    if part.last {
                        stream.outgoing_end = Some(ErrorCode::NoError);
                    }
                    Some(stream_id)
                } else {
                    None
                }
            } else {
                None
            }
        });
        if let Some(stream_id) = stream_id {
            self.send_outg_stream(stream_id)
        } else {
            Box::new(futures::finished(self))
        }
    }

    fn process_response_end(self, stream_id: StreamId, error_code: ErrorCode) -> HttpFuture<Self> {
        let stream_id = self.inner.with(move |inner: &mut ServerInner| {
            let stream = inner.streams.get_mut(stream_id);
            if let Some(stream) = stream {
                if stream.outgoing_end.is_none() {
                    stream.outgoing_end = Some(error_code);
                }
                Some(stream_id)
            } else {
                None
            }
        });
        if let Some(stream_id) = stream_id {
            self.send_outg_stream(stream_id)
        } else {
            Box::new(futures::finished(self))
        }
    }

    fn process_message(self, message: ServerToWriteMessage) -> HttpFuture<Self> {
        match message {
            ServerToWriteMessage::ResponsePart(stream_id, response) => {
                self.process_response_part(stream_id, response)
            },
            ServerToWriteMessage::ResponseStreamEnd(stream_id, error_code) => {
                self.process_response_end(stream_id, error_code)
            },
            ServerToWriteMessage::Common(common) => {
                self.process_common(common)
            },
        }
    }

    fn run(self, requests: HttpFutureStream<ServerToWriteMessage>) -> HttpFuture<()> {
        let requests = requests.map_err(Error::from);
        Box::new(requests
            .fold(self, move |wl, message: ServerToWriteMessage| {
                wl.process_message(message)
            })
            .map(|_| ()))
    }
}

impl ServerCommandLoop {
    fn process_dump_state(self, sender: futures::sync::oneshot::Sender<ConnectionStateSnapshot>) -> HttpFuture<Self> {
        // ignore send error, client might be already dead
        drop(sender.send(self.inner.with(|inner| inner.dump_state())));
        Box::new(futures::finished(self))
    }

    fn process_message(self, message: ServerCommandMessage) -> HttpFuture<Self> {
        match message {
            ServerCommandMessage::DumpState(sender) => self.process_dump_state(sender),
        }
    }

    pub fn run(self, requests: HttpFutureStreamSend<ServerCommandMessage>) -> HttpFuture<()> {
        let requests = requests.map_err(Error::from);
        Box::new(requests
            .fold(self, move |l, message: ServerCommandMessage| {
                l.process_message(message)
            })
            .map(|_| ()))
    }}

pub struct ServerConnection {
    command_tx: futures::sync::mpsc::UnboundedSender<ServerCommandMessage>,
}

impl ServerConnection {
    fn connected<F, I>(lh: &reactor::Handle, socket: HttpFutureSend<I>, _conf: ServerConf, service: Arc<F>)
                       -> (ServerConnection, HttpFuture<()>)
        where
            F : Service,
            I : AsyncRead + AsyncWrite + Send + 'static,
    {
        let lh = lh.clone();

        let (to_write_tx, to_write_rx) = futures::sync::mpsc::unbounded::<ServerToWriteMessage>();
        let (command_tx, command_rx) = futures::sync::mpsc::unbounded::<ServerCommandMessage>();

        let to_write_rx = to_write_rx.map_err(|()| Error::IoError(io::Error::new(io::ErrorKind::Other, "to_write")));
        let command_rx = Box::new(command_rx.map_err(|()| Error::IoError(io::Error::new(io::ErrorKind::Other, "command"))));

        let handshake = socket.and_then(server_handshake);

        let run = handshake.and_then(move |socket| {
            let (read, write) = socket.split();

            let inner = TaskRcMut::new(ConnData::new(
                lh,
                ServerConnData {
                    factory: service,
                },
                to_write_tx.clone()));

            let run_write = ServerWriteLoop { write: write, inner: inner.clone() }.run(Box::new(to_write_rx));
            let run_read = ServerReadLoop { read: read, inner: inner.clone() }.run();
            let run_command = ServerCommandLoop { inner: inner.clone() }.run(command_rx);

            run_write.join(run_read).join(run_command).map(|_| ())
        });

        let future = Box::new(run.then(|x| { info!("connection end: {:?}", x); x }));

        (ServerConnection {
            command_tx: command_tx,
        }, future)
    }

    pub fn new<S>(lh: &reactor::Handle, socket: TcpStream, tls: ServerTlsOption, conf: ServerConf, service: Arc<S>)
                  -> (ServerConnection, HttpFuture<()>)
        where
            S : Service,
    {
        match tls {
            ServerTlsOption::Plain =>
                ServerConnection::connected(
                    lh, Box::new(futures::finished(socket)), conf, service),
            ServerTlsOption::Tls(acceptor) =>
                ServerConnection::connected(
                    lh, Box::new(acceptor.accept_async(socket).map_err(Error::from)), conf, service),
        }
    }

    pub fn new_plain<S>(lh: &reactor::Handle, socket: TcpStream, conf: ServerConf, service: Arc<S>)
                        -> (ServerConnection, HttpFuture<()>)
        where
            S : Service,
    {
        ServerConnection::new(lh, socket, ServerTlsOption::Plain, conf, service)
    }

    pub fn new_plain_fn<F>(lh: &reactor::Handle, socket: TcpStream, conf: ServerConf, f: F)
                           -> (ServerConnection, HttpFuture<()>)
        where
            F : Fn(Headers, HttpPartStream) -> Response + Send + 'static,
    {
        struct HttpServiceFn<F>(F);

        impl<F> Service for HttpServiceFn<F>
            where F : Fn(Headers, HttpPartStream) -> Response + Send + 'static
        {
            fn start_request(&self, headers: Headers, req: HttpPartStream) -> Response {
                (self.0)(headers, req)
            }
        }

        ServerConnection::new_plain(lh, socket, conf, Arc::new(HttpServiceFn(f)))
    }

    /// For tests
    pub fn dump_state(&self) -> HttpFutureSend<ConnectionStateSnapshot> {
        let (tx, rx) = futures::oneshot();

        self.command_tx.clone().send(ServerCommandMessage::DumpState(tx))
            .expect("send request to dump state");

        let rx = rx.map_err(|_| Error::from(io::Error::new(io::ErrorKind::Other, "oneshot canceled")));

        Box::new(rx)
    }

}
<|endoftext|>


<commit_before>mod error;

use std::convert::{TryFrom, TryInto};

use fleetspeak::Packet;

use crate::action;
pub use self::error::{Error, ParseError};

pub type Result<T> = std::result::Result<T, Error>;

pub type Handler<R> = fn(&mut Action, R) -> Result<()>;

pub fn handle<R, M>(handler: Handler<R>, message: M) -> Result<()>
where
    R: action::Request,
    M: TryInto<Request<R>, Error=ParseError>,
{
    let request = message.try_into()?;

    let mut session = Action::new(request.session_id, request.request_id);
    handler(&mut session, request.data)
}

pub trait Session {
    fn send<R: action::Response>(&mut self, response: R) -> Result<()>;
}

pub struct Action {
    id: String,
    request_id: u64,
    next_response_id: u64,
}

impl Action {

    pub fn new(session_id: String, request_id: u64) -> Action {
        Action {
            id: session_id,
            request_id: request_id,
            next_response_id: 0,
        }
    }
}

impl Session for Action {

    fn send<R: action::Response>(&mut self, response: R) -> Result<()> {
        Response {
            session_id: self.id.clone(),
            request_id: Some(self.request_id),
            response_id: Some(self.next_response_id),
            data: response,
        }.send()?;

        self.next_response_id += 1;

        Ok(())
    }
}

pub struct Sink {
    id: &'static str,
}

impl Session for Sink {

    fn send<R: action::Response>(&mut self, response: R) -> Result<()> {
        Response {
            session_id: String::from(self.id),
            request_id: None,
            response_id: None,
            data: response,
        }.send()
    }
}

pub fn startup() -> Sink {
    Sink { id: "/flows/F:Startup" }
}

// TODO: This type should not be exposed.
pub struct Request<R: action::Request> {
    pub name: String,
    pub session_id: String,
    pub request_id: u64,
    pub data: R,
}

impl<R: action::Request> TryFrom<rrg_proto::GrrMessage> for Request<R> {

    type Error = ParseError;

    fn try_from(message: rrg_proto::GrrMessage)
    -> std::result::Result<Request<R>, ParseError>
    {
        use ParseError::*;

        let name = message.name.ok_or(MissingField("action name"))?;
        let session_id = message.session_id.ok_or(MissingField("session id"))?;
        let request_id = message.request_id.ok_or(MissingField("request id"))?;

        let proto = match message.args {
            Some(bytes) => prost::Message::decode(&bytes[..])?,
            None => Default::default(),
        };

        Ok(Request {
            name: name,
            session_id: session_id,
            request_id: request_id,
            data: R::from_proto(proto),
        })
    }
}

struct Response<R: action::Response> {
    session_id: String,
    request_id: Option<u64>,
    response_id: Option<u64>,
    data: R,
}

impl<R: action::Response> Response<R> {

    fn send(self) -> Result<()> {
        let message: rrg_proto::GrrMessage = self.try_into()?;

        let packet = Packet {
            service: String::from("GRR"),
            kind: Some(String::from("GrrMessage")),
            data: message,
        };

        use fleetspeak::WriteError::*;
        match fleetspeak::send(packet) {
            Ok(()) => Ok(()),
            Err(Encode(error)) => Err(error.into()),
            Err(Output(error)) => {
                // If we failed to deliver the message through Fleetspeak, it
                // means that our communication is broken (e.g. the pipe was
                // closed) and the agent should be killed.
                panic!("message delivery failure: {}", error)
            }
        }
    }
}

impl<R: action::Response> TryInto<rrg_proto::GrrMessage> for Response<R> {

    type Error = prost::EncodeError;

    fn try_into(self)
    -> std::result::Result<rrg_proto::GrrMessage, prost::EncodeError>
    {
        let mut data = Vec::new();
        prost::Message::encode(&self.data.into_proto(), &mut data)?;

        Ok(rrg_proto::GrrMessage {
            session_id: Some(self.session_id),
            response_id: self.response_id,
            request_id: self.request_id,
            r#type: Some(rrg_proto::grr_message::Type::Message.into()),
            args_rdf_name: R::RDF_NAME.map(String::from),
            args: Some(data),
            ..Default::default()
        })
    }
}
<commit_msg>Create a type for representing session statuses.<commit_after>mod error;

use std::convert::{TryFrom, TryInto};

use fleetspeak::Packet;

use crate::action;
pub use self::error::{Error, ParseError};

pub type Result<T> = std::result::Result<T, Error>;

pub type Handler<R> = fn(&mut Action, R) -> Result<()>;

pub fn handle<R, M>(handler: Handler<R>, message: M) -> Result<()>
where
    R: action::Request,
    M: TryInto<Request<R>, Error=ParseError>,
{
    let request = message.try_into()?;

    let mut session = Action::new(request.session_id, request.request_id);
    handler(&mut session, request.data)
}

pub trait Session {
    fn send<R: action::Response>(&mut self, response: R) -> Result<()>;
}

pub struct Action {
    id: String,
    request_id: u64,
    next_response_id: u64,
}

impl Action {

    pub fn new(session_id: String, request_id: u64) -> Action {
        Action {
            id: session_id,
            request_id: request_id,
            next_response_id: 0,
        }
    }
}

impl Session for Action {

    fn send<R: action::Response>(&mut self, response: R) -> Result<()> {
        Response {
            session_id: self.id.clone(),
            request_id: Some(self.request_id),
            response_id: Some(self.next_response_id),
            data: response,
        }.send()?;

        self.next_response_id += 1;

        Ok(())
    }
}

pub struct Sink {
    id: &'static str,
}

impl Session for Sink {

    fn send<R: action::Response>(&mut self, response: R) -> Result<()> {
        Response {
            session_id: String::from(self.id),
            request_id: None,
            response_id: None,
            data: response,
        }.send()
    }
}

pub fn startup() -> Sink {
    Sink { id: "/flows/F:Startup" }
}

// TODO: This type should not be exposed.
pub struct Request<R: action::Request> {
    pub name: String,
    pub session_id: String,
    pub request_id: u64,
    pub data: R,
}

impl<R: action::Request> TryFrom<rrg_proto::GrrMessage> for Request<R> {

    type Error = ParseError;

    fn try_from(message: rrg_proto::GrrMessage)
    -> std::result::Result<Request<R>, ParseError>
    {
        use ParseError::*;

        let name = message.name.ok_or(MissingField("action name"))?;
        let session_id = message.session_id.ok_or(MissingField("session id"))?;
        let request_id = message.request_id.ok_or(MissingField("request id"))?;

        let proto = match message.args {
            Some(bytes) => prost::Message::decode(&bytes[..])?,
            None => Default::default(),
        };

        Ok(Request {
            name: name,
            session_id: session_id,
            request_id: request_id,
            data: R::from_proto(proto),
        })
    }
}

struct Response<R: action::Response> {
    session_id: String,
    request_id: Option<u64>,
    response_id: Option<u64>,
    data: R,
}

impl<R: action::Response> Response<R> {

    fn send(self) -> Result<()> {
        let message: rrg_proto::GrrMessage = self.try_into()?;

        let packet = Packet {
            service: String::from("GRR"),
            kind: Some(String::from("GrrMessage")),
            data: message,
        };

        use fleetspeak::WriteError::*;
        match fleetspeak::send(packet) {
            Ok(()) => Ok(()),
            Err(Encode(error)) => Err(error.into()),
            Err(Output(error)) => {
                // If we failed to deliver the message through Fleetspeak, it
                // means that our communication is broken (e.g. the pipe was
                // closed) and the agent should be killed.
                panic!("message delivery failure: {}", error)
            }
        }
    }
}

impl<R: action::Response> TryInto<rrg_proto::GrrMessage> for Response<R> {

    type Error = prost::EncodeError;

    fn try_into(self)
    -> std::result::Result<rrg_proto::GrrMessage, prost::EncodeError>
    {
        let mut data = Vec::new();
        prost::Message::encode(&self.data.into_proto(), &mut data)?;

        Ok(rrg_proto::GrrMessage {
            session_id: Some(self.session_id),
            response_id: self.response_id,
            request_id: self.request_id,
            r#type: Some(rrg_proto::grr_message::Type::Message.into()),
            args_rdf_name: R::RDF_NAME.map(String::from),
            args: Some(data),
            ..Default::default()
        })
    }
}

struct Status {
    session_id: String,
    request_id: u64,
    result: Result<()>,
}

impl TryInto<rrg_proto::GrrMessage> for Status {

    type Error = prost::EncodeError;

    fn try_into(self)
    -> std::result::Result<rrg_proto::GrrMessage, prost::EncodeError> {
        let status = match self.result {
            Ok(()) => rrg_proto::GrrStatus {
                status: Some(rrg_proto::grr_status::ReturnedStatus::Ok.into()),
                ..Default::default()
            },
            Err(error) => rrg_proto::GrrStatus {
                status: Some(rrg_proto::grr_status::ReturnedStatus::GenericError.into()),
                error_message: Some(error.to_string()),
                ..Default::default()
            },
        };

        let mut data = Vec::new();
        prost::Message::encode(&status, &mut data)?;

        Ok(rrg_proto::GrrMessage {
            session_id: Some(self.session_id),
            response_id: Some(self.request_id),
            r#type: Some(rrg_proto::grr_message::Type::Status.into()),
            args_rdf_name: Some(String::from("GrrStatus")),
            args: Some(data),
            ..Default::default()
        })
    }
}
<|endoftext|>


<commit_before>use super::column::Column;

pub struct Row {
    columns: Vec<Column>
}

impl Row {
    fn new() -> Self {
        Row { columns: Vec::new() }
    }
}
<commit_msg>redesigned row to take in talbe and act as file interface<commit_after>use super::column::Column;
use super::table::Table;

pub struct Rows<'a> {
    table: Table<'a>
}

// TODO: implement insert_row and select_row
impl<'a> Rows<'a> {
    pub fn new<'b>(table: Table<'b>) -> Rows<'b> {
        // TODO: implement new rows
    }
}
<|endoftext|>