<commit_before>use luminance_gl::gl33::Tessellation;
use std::collections::BTreeMap;
//use std::fs::File;
//use std::io::Read;
use std::path::{Path, PathBuf};
use wavefront_obj::{self, obj};

// FIXME: implement materials
type Material = ();

pub type Vertex = (VertexPos, VertexNor, VertexTexCoord);
pub type VertexPos = [f32; 3];
pub type VertexNor = [f32; 3];
pub type VertexTexCoord = [f32; 2];

pub struct Model<'a> {
  parts: Vec<Part<'a>>
}

impl<'a> Model<'a> {
  pub fn from_parts(parts: Vec<Part<'a>>) -> Self {
    Model {
      parts: parts
    }
  }
}

pub struct Part<'a> {
  tess: Tessellation,
  mat: Option<&'a Material>
}

impl<'a> Part<'a> {
  pub fn new(tess: Tessellation, mat: Option<&'a Material>) -> Self {
    Part {
      tess: tess,
      mat: mat
    }
  }

  pub fn tessellation(&self) -> &Tessellation {
    &self.tess
  }

  pub fn material(&self) -> Option<&Material> {
    self.mat.clone()
  }
}

// FIXME: review all the code bellow
////pub fn load<P>(path: P, mode: tessellation::Mode) -> Result<gl33::Tessellation, TessellationError> where P: AsRef<Path> {
////  let path = path.as_ref();
////
////  info!("loading tessellation: \x1b[35m{:?}", path);
////
////  let mut input = String::new();
////
////  // load the data directly into memory; no buffering nor streaming
////  {
////    let mut file = try!(File::open(path).map_err(|e| TessellationError::FileNotFound(path.to_path_buf(), format!("{:?}", e))));
////    let _ = file.read_to_string(&mut input);
////  }
////
////  // parse the obj file and convert it
////  let obj_set = try!(obj::parse(input).map_err(TessellationError::ParseFailed));
////
////  convert_obj(obj_set, mode)
////}
////
////// Turn a loaded wavefront obj object into a `Model`
////fn convert_obj(obj_set: obj::ObjSet, mode: tessellation::Mode) -> Result<gl33::Tessellation, TessellationError> {
////  if obj_set.objects.len() != 1 {
////    return Err(TessellationError::MultiObjects);
////  }
////
////  let obj = &obj_set.objects[0];
////  info!("  found object \x1b[35m{}", obj.name);
////
////  // interleave the vertices
////  let interleaved_vertices = interleave_vertices(&obj.vertices, &obj.normals, &obj.tex_vertices);
////
////  Err(TessellationError::Error)
////}

// Convert wavefront_obj’s Geometry into a pair of vertices and indices.
//
// This function will regenerate the indices on the fly based on which are used in the shapes in the
// geometry. It’s used to create independent tessellation.
fn convert_geometry(geo: &obj::Geometry, positions: &[obj::Vertex], normals: &[obj::Normal], tvertices: &[obj::TVertex]) -> Result<(Vec<Vertex>, Vec<u32>), ModelError> {
  let mut vertices = Vec::new(); // FIXME: better allocation scheme?
  let mut indices = Vec::new();
  let mut index_map = BTreeMap::new();

  for prim in geo.shapes.iter().map(|s| s.primitive) {
    let keys = try!(create_keys_from_primitive(prim));

    for key in keys {
      match index_map.get(&key).map(|i: &u32| *i) {
        Some(index) => {
          // that triplet already exists; just append the index in the indices buffer
          indices.push(index);
        },
        None => {
          // this is a new, not yet discovered triplet; create the corresponding vertex and add it
          // to the vertices buffer, and map the triplet to the index in the indices buffer
          let vertex = interleave_vertex(&positions[key.0], &normals[key.1], &tvertices[key.2]);
          let index = vertices.len() as u32;

          vertices.push(vertex);
          indices.push(index);
          index_map.insert(key, index);
        }
      }
    }
  }

  Ok((vertices, indices))
}

// Create triplet keys from wavefront_obj primitives. If any primitive doesn’t have all the triplet
// information (position, normal, tex), a ModelError::UnsupportedVertex error is returned instead.
fn create_keys_from_primitive(prim: obj::Primitive) -> Result<Vec<(usize, usize, usize)>, ModelError> {
  match prim {
    obj::Primitive::Point(i) => {
      let a = try!(vtnindex_to_key(i));
      Ok(vec![a])
    },
    obj::Primitive::Line(i, j) => {
      let a = try!(vtnindex_to_key(i));
      let b = try!(vtnindex_to_key(j));
      Ok(vec![a, b])
    },
    obj::Primitive::Triangle(i, j, k) => {
      let a = try!(vtnindex_to_key(i));
      let b = try!(vtnindex_to_key(j));
      let c = try!(vtnindex_to_key(k));
      Ok(vec![a, b, c])
    }
  }
}

// Convert from a wavefront_obj VTNIndex into our triplet, raising error if not possible.
fn vtnindex_to_key(i: obj::VTNIndex) -> Result<(usize, usize, usize), ModelError> {
  match i {
    (pi, Some(ti), Some(ni)) => Ok((pi, ni, ti)),
    _ => Err(ModelError::UnsupportedVertex)
  }
}

fn interleave_vertex(p: &obj::Vertex, n: &obj::Normal, t: &obj::TVertex) -> Vertex {
  (convert_vertex(p), convert_nor(n), convert_tvertex(t))
}

fn convert_vertex(v: &obj::Vertex) -> VertexPos {
  [v.x as f32, v.y as f32, v.z as f32]
}

fn convert_nor(n: &obj::Normal) -> VertexNor {
  convert_vertex(n)
}

fn convert_tvertex(t: &obj::TVertex) -> VertexTexCoord {
  [t.x as f32, t.y as f32]
}

////mod hot {
////  use super::{TessellationError, Vertex};
////
////  use luminance::tessellation;
////  use luminance_gl::gl33;
////  use resource::ResourceManager;
////  use std::ops::Deref;
////  use std::path::{Path, PathBuf};
////
////  pub struct Tessellation {
////    path: PathBuf,
////    mode: tessellation::Mode,
////    tess: gl33::Tessellation
////  }
////
////  impl Tessellation {
////    fn load<P>(manager: &mut ResourceManager, path: P, mode: tessellation::Mode) -> Result<Self, TessellationError> where P: AsRef<Path> {
////      Err(TessellationError::Error)
////    }
////  }
////
////  impl Deref for Tessellation {
////    type Target = gl33::Tessellation;
////
////    fn deref(&self) -> &Self::Target {
////      &self.tess
////    }
////  }
////}
////
pub enum ModelError {
  FileNotFound(PathBuf, String),
  ParseFailed(wavefront_obj::ParseError),
  MultiObjects,
  UnsupportedVertex
}
<commit_msg>Better λ in convert_geometry. (#3, #9)<commit_after>use luminance_gl::gl33::Tessellation;
use std::collections::BTreeMap;
//use std::fs::File;
//use std::io::Read;
use std::path::{Path, PathBuf};
use wavefront_obj::{self, obj};

// FIXME: implement materials
type Material = ();

pub type Vertex = (VertexPos, VertexNor, VertexTexCoord);
pub type VertexPos = [f32; 3];
pub type VertexNor = [f32; 3];
pub type VertexTexCoord = [f32; 2];

pub struct Model<'a> {
  parts: Vec<Part<'a>>
}

impl<'a> Model<'a> {
  pub fn from_parts(parts: Vec<Part<'a>>) -> Self {
    Model {
      parts: parts
    }
  }
}

pub struct Part<'a> {
  tess: Tessellation,
  mat: Option<&'a Material>
}

impl<'a> Part<'a> {
  pub fn new(tess: Tessellation, mat: Option<&'a Material>) -> Self {
    Part {
      tess: tess,
      mat: mat
    }
  }

  pub fn tessellation(&self) -> &Tessellation {
    &self.tess
  }

  pub fn material(&self) -> Option<&Material> {
    self.mat.clone()
  }
}

// FIXME: review all the code bellow
////pub fn load<P>(path: P, mode: tessellation::Mode) -> Result<gl33::Tessellation, TessellationError> where P: AsRef<Path> {
////  let path = path.as_ref();
////
////  info!("loading tessellation: \x1b[35m{:?}", path);
////
////  let mut input = String::new();
////
////  // load the data directly into memory; no buffering nor streaming
////  {
////    let mut file = try!(File::open(path).map_err(|e| TessellationError::FileNotFound(path.to_path_buf(), format!("{:?}", e))));
////    let _ = file.read_to_string(&mut input);
////  }
////
////  // parse the obj file and convert it
////  let obj_set = try!(obj::parse(input).map_err(TessellationError::ParseFailed));
////
////  convert_obj(obj_set, mode)
////}
////
////// Turn a loaded wavefront obj object into a `Model`
////fn convert_obj(obj_set: obj::ObjSet, mode: tessellation::Mode) -> Result<gl33::Tessellation, TessellationError> {
////  if obj_set.objects.len() != 1 {
////    return Err(TessellationError::MultiObjects);
////  }
////
////  let obj = &obj_set.objects[0];
////  info!("  found object \x1b[35m{}", obj.name);
////
////  // interleave the vertices
////  let interleaved_vertices = interleave_vertices(&obj.vertices, &obj.normals, &obj.tex_vertices);
////
////  Err(TessellationError::Error)
////}

// Convert wavefront_obj’s Geometry into a pair of vertices and indices.
//
// This function will regenerate the indices on the fly based on which are used in the shapes in the
// geometry. It’s used to create independent tessellation.
fn convert_geometry(geo: &obj::Geometry, positions: &[obj::Vertex], normals: &[obj::Normal], tvertices: &[obj::TVertex]) -> Result<(Vec<Vertex>, Vec<u32>), ModelError> {
  let mut vertices = Vec::new(); // FIXME: better allocation scheme?
  let mut indices = Vec::new();
  let mut index_map = BTreeMap::new();

  for prim in geo.shapes.iter().map(|s| s.primitive) {
    let keys = try!(create_keys_from_primitive(prim));

    for key in keys {
      match index_map.get(&key).map(|&i| i) {
        Some(index) => {
          // that triplet already exists; just append the index in the indices buffer
          indices.push(index);
        },
        None => {
          // this is a new, not yet discovered triplet; create the corresponding vertex and add it
          // to the vertices buffer, and map the triplet to the index in the indices buffer
          let vertex = interleave_vertex(&positions[key.0], &normals[key.1], &tvertices[key.2]);
          let index = vertices.len() as u32;

          vertices.push(vertex);
          indices.push(index);
          index_map.insert(key, index);
        }
      }
    }
  }

  Ok((vertices, indices))
}

// Create triplet keys from wavefront_obj primitives. If any primitive doesn’t have all the triplet
// information (position, normal, tex), a ModelError::UnsupportedVertex error is returned instead.
fn create_keys_from_primitive(prim: obj::Primitive) -> Result<Vec<(usize, usize, usize)>, ModelError> {
  match prim {
    obj::Primitive::Point(i) => {
      let a = try!(vtnindex_to_key(i));
      Ok(vec![a])
    },
    obj::Primitive::Line(i, j) => {
      let a = try!(vtnindex_to_key(i));
      let b = try!(vtnindex_to_key(j));
      Ok(vec![a, b])
    },
    obj::Primitive::Triangle(i, j, k) => {
      let a = try!(vtnindex_to_key(i));
      let b = try!(vtnindex_to_key(j));
      let c = try!(vtnindex_to_key(k));
      Ok(vec![a, b, c])
    }
  }
}

// Convert from a wavefront_obj VTNIndex into our triplet, raising error if not possible.
fn vtnindex_to_key(i: obj::VTNIndex) -> Result<(usize, usize, usize), ModelError> {
  match i {
    (pi, Some(ti), Some(ni)) => Ok((pi, ni, ti)),
    _ => Err(ModelError::UnsupportedVertex)
  }
}

fn interleave_vertex(p: &obj::Vertex, n: &obj::Normal, t: &obj::TVertex) -> Vertex {
  (convert_vertex(p), convert_nor(n), convert_tvertex(t))
}

fn convert_vertex(v: &obj::Vertex) -> VertexPos {
  [v.x as f32, v.y as f32, v.z as f32]
}

fn convert_nor(n: &obj::Normal) -> VertexNor {
  convert_vertex(n)
}

fn convert_tvertex(t: &obj::TVertex) -> VertexTexCoord {
  [t.x as f32, t.y as f32]
}

////mod hot {
////  use super::{TessellationError, Vertex};
////
////  use luminance::tessellation;
////  use luminance_gl::gl33;
////  use resource::ResourceManager;
////  use std::ops::Deref;
////  use std::path::{Path, PathBuf};
////
////  pub struct Tessellation {
////    path: PathBuf,
////    mode: tessellation::Mode,
////    tess: gl33::Tessellation
////  }
////
////  impl Tessellation {
////    fn load<P>(manager: &mut ResourceManager, path: P, mode: tessellation::Mode) -> Result<Self, TessellationError> where P: AsRef<Path> {
////      Err(TessellationError::Error)
////    }
////  }
////
////  impl Deref for Tessellation {
////    type Target = gl33::Tessellation;
////
////    fn deref(&self) -> &Self::Target {
////      &self.tess
////    }
////  }
////}
////
pub enum ModelError {
  FileNotFound(PathBuf, String),
  ParseFailed(wavefront_obj::ParseError),
  MultiObjects,
  UnsupportedVertex
}
<|endoftext|>


<commit_before>use core::result;
use core::fmt::Debug;

use ctx::{TryFromCtx, TryRefFromCtx};
use error;
use endian::Endian;

/// A very generic, contextual pread interface in Rust. Allows completely parallelized reads, as `Self` is immutable
///
/// Don't be scared! The `Pread` definition _is_ terrifying, but it is definitely tractable. Essentially, `E` is the error, `Ctx` the parsing context, `I` is the indexing type, `TryCtx` is the "offset + ctx" Context given to the `TryFromCtx` trait bounds, and `SliceCtx` is the "offset + size + ctx" context given to the `TryRefFromCtx` trait bound.
///
/// They all have reasonable defaults, so if you're just using this trait, you can usually get away with `fn <T: scroll::Pread>(bytes: &T) -> yourResultWhichConvertsScrollErrors`
///
/// # Implementing Your Own Reader
/// If you want to implement your own reader for a type `Foo` from some kind of buffer (say `[u8]`), then you need to implement `TryFromCtx`
///
/// ```rust
/// use scroll::{self, ctx};
///  #[derive(Debug, PartialEq, Eq)]
///  pub struct Foo(u16);
///
///  impl<'a> ctx::TryFromCtx<'a> for Foo {
///      type Error = scroll::Error;
///      fn try_from_ctx(this: &'a [u8], ctx: (usize, scroll::Endian)) -> Result<Self, Self::Error> {
///          use scroll::Pread;
///          let offset = ctx.0;
///          let le = ctx.1;
///          if offset > 2 { return Err((scroll::Error::BadOffset("whatever".to_string())).into()) }
///          let n = this.pread_with(offset, le)?;
///          Ok(Foo(n))
///      }
///  }
///
/// use scroll::Pread;
/// // you can now read `Foo`'s out of a &[u8] buffer for free, with `Pread` and `Gread` without doing _anything_ else!
/// let bytes: [u8; 4] = [0xde, 0xad, 0, 0];
/// let foo = bytes.pread::<Foo>(0).unwrap();
/// assert_eq!(Foo(0xadde), foo);
/// let foo2 = bytes.pread_with::<Foo>(0, scroll::BE).unwrap();
/// assert_eq!(Foo(0xdeadu16), foo2);
/// ```
///
/// # Advanced: Using Your Own Error in `TryFromCtx`
/// ```rust
///  use scroll::{self, ctx};
///  use std::error;
///  use std::fmt::{self, Display};
///  // make some kind of normal error which also can transform a scroll error ideally (quick_error, error_chain allow this automatically nowadays)
///  #[derive(Debug)]
///  pub struct ExternalError {}
///
///  impl Display for ExternalError {
///      fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
///          write!(fmt, "ExternalError")
///      }
///  }
///
///  impl error::Error for ExternalError {
///      fn description(&self) -> &str {
///          "ExternalError"
///      }
///      fn cause(&self) -> Option<&error::Error> { None}
///  }
///
///  impl From<scroll::Error> for ExternalError {
///      fn from(err: scroll::Error) -> Self {
///          match err {
///              _ => ExternalError{},
///          }
///      }
///  }
///  #[derive(Debug, PartialEq, Eq)]
///  pub struct Foo(u16);
///
///  impl<'a> ctx::TryFromCtx<'a> for Foo {
///      type Error = ExternalError;
///      fn try_from_ctx(this: &'a [u8], ctx: (usize, scroll::Endian)) -> Result<Self, Self::Error> {
///          use scroll::Pread;
///          let offset = ctx.0;
///          let le = ctx.1;
///          if offset > 2 { return Err((ExternalError {}).into()) }
///          let n = this.pread_with(offset, le)?;
///          Ok(Foo(n))
///      }
///  }
///
/// use scroll::Pread;
/// // the only caveat is that you now need to specify the error type in fn generic params, e.g. `fn thingee<S: scroll::Pread<ExternalError>>`
/// let bytes: [u8; 4] = [0xde, 0xad, 0, 0];
/// let foo: Result<Foo, ExternalError> = bytes.pread(0);
/// ```

pub trait Pread<Ctx = Endian, E = error::Error, I = usize, TryCtx = (I, Ctx), SliceCtx = (I, I, Ctx) >
 where E: Debug,
       Ctx: Copy + Default + Debug,
       I: Copy + Debug,
       TryCtx: Copy + Default + Debug,
       SliceCtx: Copy + Default + Debug,
{
    #[inline]
    /// Implement this if you need a faster version for use by `Gread`
    fn pread_unsafe<'a, N: TryFromCtx<'a, TryCtx, Error = E>>(&'a self, offset: I, ctx: Ctx) -> N {
        self.pread_with(offset, ctx).unwrap()
    }
    #[inline]
    /// Reads a value from `self` at `offset` with a default `Ctx`. For the primitive numeric values, this will read at the machine's endianness.
    /// # Example
    /// ```rust
    /// use scroll::Pread;
    /// let bytes = [0x7fu8; 0x01];
    /// let byte = bytes.pread::<u8>(0).unwrap();
    fn pread<'a, N: TryFromCtx<'a, TryCtx, Error = E>>(&'a self, offset: I) -> result::Result<N, E> {
        self.pread_with(offset, Ctx::default())
    }
    #[inline]
    /// Reads a value from `self` at `offset` with the given `ctx`
    /// # Example
    /// ```rust
    /// use scroll::Pread;
    /// let bytes: [u8; 2] = [0xde, 0xad];
    /// let dead: u16 = bytes.pread_with(0, scroll::BE).unwrap();
    /// assert_eq!(dead, 0xdeadu16);
    fn pread_with<'a, N: TryFromCtx<'a, TryCtx, Error = E>>(&'a self, offset: I, ctx: Ctx) -> result::Result<N, E>;
    /// Slices an `N` from `self` at `offset` up to `count` times
    #[inline]
    /// # Example
    /// ```rust
    /// use scroll::Pread;
    /// let bytes: [u8; 2] = [0x48, 0x49];
    /// let hi: &str = bytes.pread_slice(0, 2).unwrap();
    /// assert_eq!(hi, "HI");
    /// let bytes2 = bytes.pread_slice::<[u8]>(0, 2).unwrap();
    /// assert_eq!(bytes, bytes2);
    fn pread_slice<'a, N: ?Sized + TryRefFromCtx<SliceCtx, Error = E>>(&'a self, offset: I, count: I) -> result::Result<&'a N, E>;
}

impl<Ctx, E> Pread<Ctx, E> for [u8]
    where
    E: Debug,
    Ctx: Debug + Copy + Default {
    #[inline]
    fn pread_unsafe<'a, N: TryFromCtx<'a, (usize, Ctx), Error = E>>(&'a self, offset: usize, le: Ctx) -> N {
        TryFromCtx::try_from_ctx(self, (offset, le)).unwrap()
    }
    #[inline]
    fn pread_with<'a, N: TryFromCtx<'a, (usize, Ctx), Error = E>>(&'a self, offset: usize, le: Ctx) -> result::Result<N, E> {
        TryFromCtx::try_from_ctx(self, (offset, le))
    }
    #[inline]
    fn pread_slice<N: ?Sized + TryRefFromCtx<(usize, usize, Ctx), Error = E>>(&self, offset: usize, count: usize) -> result::Result<&N, E> {
        TryRefFromCtx::try_ref_from_ctx(self, (offset, count, Ctx::default()))
    }
}

impl<Ctx, E, T> Pread<Ctx, E> for T
    where
    E: Debug,
    Ctx: Debug + Copy + Default,
    T: AsRef<[u8]> {
    #[inline]
    fn pread_unsafe<'a, N: TryFromCtx<'a, (usize, Ctx), Error = E>>(&'a self, offset: usize, le: Ctx) -> N {
        <[u8] as Pread<Ctx, E>>::pread_unsafe::<N>(self.as_ref(), offset, le)
    }
    #[inline]
    fn pread_with<'a, N: TryFromCtx<'a, (usize, Ctx), Error = E>>(&'a self, offset: usize, le: Ctx) -> result::Result<N, E> {
        TryFromCtx::try_from_ctx(self.as_ref(), (offset, le))
    }
    #[inline]
    fn pread_slice<N: ?Sized + TryRefFromCtx<(usize, usize, Ctx), Error = E>>(&self, offset: usize, count: usize) -> result::Result<&N, E> {
        <[u8] as Pread<Ctx, E>>::pread_slice::<N>(self.as_ref(), offset, count)
    }
}
<commit_msg>docs: update minor doc<commit_after>use core::result;
use core::fmt::Debug;

use ctx::{TryFromCtx, TryRefFromCtx};
use error;
use endian::Endian;

/// A very generic, contextual pread interface in Rust. Allows completely parallelized reads, as `Self` is immutable
///
/// Don't be scared! The `Pread` definition _is_ terrifying, but it is definitely tractable. Essentially, `E` is the error, `Ctx` the parsing context, `I` is the indexing type, `TryCtx` is the "offset + ctx" Context given to the `TryFromCtx` trait bounds, and `SliceCtx` is the "offset + size + ctx" context given to the `TryRefFromCtx` trait bound.
///
/// They all have reasonable defaults, so if you're just using this trait, you can usually get away with `fn <T: scroll::Pread>(bytes: &T) -> yourResultWhichConvertsScrollErrors`
///
/// # Implementing Your Own Reader
/// If you want to implement your own reader for a type `Foo` from some kind of buffer (say `[u8]`), then you need to implement `TryFromCtx`
///
/// ```rust
/// use scroll::{self, ctx};
///  #[derive(Debug, PartialEq, Eq)]
///  pub struct Foo(u16);
///
///  impl<'a> ctx::TryFromCtx<'a> for Foo {
///      type Error = scroll::Error;
///      fn try_from_ctx(this: &'a [u8], ctx: (usize, scroll::Endian)) -> Result<Self, Self::Error> {
///          use scroll::Pread;
///          let offset = ctx.0;
///          let le = ctx.1;
///          if offset > 2 { return Err((scroll::Error::BadOffset("whatever".to_string())).into()) }
///          let n = this.pread_with(offset, le)?;
///          Ok(Foo(n))
///      }
///  }
///
/// use scroll::Pread;
/// // you can now read `Foo`'s out of a &[u8] buffer for free, with `Pread` and `Gread` without doing _anything_ else!
/// let bytes: [u8; 4] = [0xde, 0xad, 0, 0];
/// let foo = bytes.pread::<Foo>(0).unwrap();
/// assert_eq!(Foo(0xadde), foo);
/// let foo2 = bytes.pread_with::<Foo>(0, scroll::BE).unwrap();
/// assert_eq!(Foo(0xdeadu16), foo2);
/// ```
///
/// # Advanced: Using Your Own Error in `TryFromCtx`
/// ```rust
///  use scroll::{self, ctx};
///  use std::error;
///  use std::fmt::{self, Display};
///  // make some kind of normal error which also can transform a scroll error ideally (quick_error, error_chain allow this automatically nowadays)
///  #[derive(Debug)]
///  pub struct ExternalError {}
///
///  impl Display for ExternalError {
///      fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
///          write!(fmt, "ExternalError")
///      }
///  }
///
///  impl error::Error for ExternalError {
///      fn description(&self) -> &str {
///          "ExternalError"
///      }
///      fn cause(&self) -> Option<&error::Error> { None}
///  }
///
///  impl From<scroll::Error> for ExternalError {
///      fn from(err: scroll::Error) -> Self {
///          match err {
///              _ => ExternalError{},
///          }
///      }
///  }
///  #[derive(Debug, PartialEq, Eq)]
///  pub struct Foo(u16);
///
///  impl<'a> ctx::TryFromCtx<'a> for Foo {
///      type Error = ExternalError;
///      fn try_from_ctx(this: &'a [u8], ctx: (usize, scroll::Endian)) -> Result<Self, Self::Error> {
///          use scroll::Pread;
///          let offset = ctx.0;
///          let le = ctx.1;
///          if offset > 2 { return Err((ExternalError {}).into()) }
///          let n = this.pread_with(offset, le)?;
///          Ok(Foo(n))
///      }
///  }
///
/// use scroll::Pread;
/// // the only caveat is that you now need to specify the error type in fn generic params, e.g. `fn thingee<S: scroll::Pread<YourCtx, ExternalError>>`
/// let bytes: [u8; 4] = [0xde, 0xad, 0, 0];
/// let foo: Result<Foo, ExternalError> = bytes.pread(0);
/// ```

pub trait Pread<Ctx = Endian, E = error::Error, I = usize, TryCtx = (I, Ctx), SliceCtx = (I, I, Ctx) >
 where E: Debug,
       Ctx: Copy + Default + Debug,
       I: Copy + Debug,
       TryCtx: Copy + Default + Debug,
       SliceCtx: Copy + Default + Debug,
{
    #[inline]
    /// Implement this if you need a faster version for use by `Gread`
    fn pread_unsafe<'a, N: TryFromCtx<'a, TryCtx, Error = E>>(&'a self, offset: I, ctx: Ctx) -> N {
        self.pread_with(offset, ctx).unwrap()
    }
    #[inline]
    /// Reads a value from `self` at `offset` with a default `Ctx`. For the primitive numeric values, this will read at the machine's endianness.
    /// # Example
    /// ```rust
    /// use scroll::Pread;
    /// let bytes = [0x7fu8; 0x01];
    /// let byte = bytes.pread::<u8>(0).unwrap();
    fn pread<'a, N: TryFromCtx<'a, TryCtx, Error = E>>(&'a self, offset: I) -> result::Result<N, E> {
        self.pread_with(offset, Ctx::default())
    }
    #[inline]
    /// Reads a value from `self` at `offset` with the given `ctx`
    /// # Example
    /// ```rust
    /// use scroll::Pread;
    /// let bytes: [u8; 2] = [0xde, 0xad];
    /// let dead: u16 = bytes.pread_with(0, scroll::BE).unwrap();
    /// assert_eq!(dead, 0xdeadu16);
    fn pread_with<'a, N: TryFromCtx<'a, TryCtx, Error = E>>(&'a self, offset: I, ctx: Ctx) -> result::Result<N, E>;
    /// Slices an `N` from `self` at `offset` up to `count` times
    #[inline]
    /// # Example
    /// ```rust
    /// use scroll::Pread;
    /// let bytes: [u8; 2] = [0x48, 0x49];
    /// let hi: &str = bytes.pread_slice(0, 2).unwrap();
    /// assert_eq!(hi, "HI");
    /// let bytes2 = bytes.pread_slice::<[u8]>(0, 2).unwrap();
    /// assert_eq!(bytes, bytes2);
    fn pread_slice<'a, N: ?Sized + TryRefFromCtx<SliceCtx, Error = E>>(&'a self, offset: I, count: I) -> result::Result<&'a N, E>;
}

impl<Ctx, E> Pread<Ctx, E> for [u8]
    where
    E: Debug,
    Ctx: Debug + Copy + Default {
    #[inline]
    fn pread_unsafe<'a, N: TryFromCtx<'a, (usize, Ctx), Error = E>>(&'a self, offset: usize, le: Ctx) -> N {
        TryFromCtx::try_from_ctx(self, (offset, le)).unwrap()
    }
    #[inline]
    fn pread_with<'a, N: TryFromCtx<'a, (usize, Ctx), Error = E>>(&'a self, offset: usize, le: Ctx) -> result::Result<N, E> {
        TryFromCtx::try_from_ctx(self, (offset, le))
    }
    #[inline]
    fn pread_slice<N: ?Sized + TryRefFromCtx<(usize, usize, Ctx), Error = E>>(&self, offset: usize, count: usize) -> result::Result<&N, E> {
        TryRefFromCtx::try_ref_from_ctx(self, (offset, count, Ctx::default()))
    }
}

impl<Ctx, E, T> Pread<Ctx, E> for T
    where
    E: Debug,
    Ctx: Debug + Copy + Default,
    T: AsRef<[u8]> {
    #[inline]
    fn pread_unsafe<'a, N: TryFromCtx<'a, (usize, Ctx), Error = E>>(&'a self, offset: usize, le: Ctx) -> N {
        <[u8] as Pread<Ctx, E>>::pread_unsafe::<N>(self.as_ref(), offset, le)
    }
    #[inline]
    fn pread_with<'a, N: TryFromCtx<'a, (usize, Ctx), Error = E>>(&'a self, offset: usize, le: Ctx) -> result::Result<N, E> {
        TryFromCtx::try_from_ctx(self.as_ref(), (offset, le))
    }
    #[inline]
    fn pread_slice<N: ?Sized + TryRefFromCtx<(usize, usize, Ctx), Error = E>>(&self, offset: usize, count: usize) -> result::Result<&N, E> {
        <[u8] as Pread<Ctx, E>>::pread_slice::<N>(self.as_ref(), offset, count)
    }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate serde_json;
extern crate reqwest;
use self::iron::prelude::*;
use self::iron::{status, Request, Response, IronResult};

use util::{EnvVar, read_env_var};
use util::telegram::{register, unregister, send, send_with_reply_markup};
use util::twitter;
use model::telegram;

use std::io::Read;

pub fn telegram(req: &mut Request) -> IronResult<Response> {
    let mut body = String::new();
    req.body
        .read_to_string(&mut body)
        .map_err(|e| IronError::new(e, (status::BadRequest, "Error reading request")))?;
    let update: telegram::Update = serde_json::from_str(&body).unwrap();
    if let Some(msg) = update.message {
        if let Some(txt) = msg.text {
            let is_private = msg.chat.chat_type == "private";
            let identifier = format!("@{}", read_env_var(&EnvVar::Name));
            let has_identifier = txt.find(&identifier).is_some();
            let txt = strip_identifier(&txt);
            if is_private || has_identifier {
                let id = msg.chat.id;
                match txt.as_str() {
                    "/start" => respond_start(id),
                    "/help" => respond_help(id),
                    "/unsubscribe" => respond_unsubscribe(id),
                    "/delays" => respond_delays(id),
                    txt => {
                        if let Ok(num) = txt.parse::<u32>() {
                            respond_num_delays(id, num)
                        } else if is_private {
                            respond_unknown(id)
                        } else {
                            Ok(())
                        }
                    }
                }?;
            }
        }
    }
    Ok(Response::with((status::Ok, "ok")))
}

fn strip_identifier(msg: &str) -> String {
    let identifier = format!("@{}", read_env_var(&EnvVar::Name));
    let msg = if let Some(pos) = msg.find(&identifier) {
        let end = pos + identifier.len();
        msg[..pos].to_owned() + &msg[end..]
    } else {
        msg.to_owned()
    };
    msg.trim().to_owned()
}

fn respond_start(chat_id: i32) -> IronResult<()> {
    let new_registration = register(chat_id).unwrap();
    let msg = if new_registration {
        let acc = read_env_var(&EnvVar::TwitterAcc);
        let tweet = twitter::user_last_tweet(&acc).unwrap();
        format!("Successfully registered!\nLast delay:\n\n{}", tweet)
    } else {
        "This chat has already been registered".to_owned()
    };
    send(chat_id, &msg)?;
    Ok(())
}

fn respond_help(chat_id: i32) -> IronResult<()> {
    send(chat_id,
         "Available commands:\n\n\
        /start - Subscribes this chat to be notified of SBB delays\n\
        /unsubscribe - Unsubscribes this chat from the delay notifications\n\
        /delays - Shows the last `n` delays\n\
        /help - Shows this window")?;
    Ok(())
}

fn respond_unsubscribe(chat_id: i32) -> IronResult<()> {
    let unsubscribed = unregister(chat_id).unwrap();
    let msg = if unsubscribed {
        "Successfully unsubscribed from the delay notifications.\n\
        Use /start to subscribe again"
    } else {
        "This chat was not subscribed to be notified of delays in the first place, silly!\n\
        Use /start if you want to subscribe"
    };
    send(chat_id, msg)?;
    Ok(())
}

fn respond_delays(chat_id: i32) -> IronResult<()> {
    use model::telegram::{InlineKeyboardMarkup, InlineKeyboardButton};
    let mut buttons = Vec::new();
    let mut count = 1;
    for _ in 0..3 {
        let mut row = Vec::new();
        for _ in 0..3 {
            let count_str = format!("{}", count);
            let button = InlineKeyboardButton {
                text: count_str.clone(),
                switch_inline_query_current_chat: Some(count_str),
            };
            row.push(button);
            count += 1;
        }
        buttons.push(row);
    }
    let markup = InlineKeyboardMarkup { inline_keyboard: buttons };
    let msg = "How many of the last delays to you want to look up?";
    let mut s = String::new();
    send_with_reply_markup(chat_id, msg, Some(markup))?.read_to_string(&mut s).unwrap();
    Ok(())
}

fn respond_num_delays(chat_id: i32, delay_count: u32) -> IronResult<()> {
    const MIN: u32 = 1;
    const MAX: u32 = 9;
    if delay_count < MIN || delay_count > MAX {
        let msg = format!("Invalid number of delays selected, \
            please enter a number between {} and {}.",
                          MIN,
                          MAX);
        send(chat_id, &msg)?;
        return Ok(());
    }
    let acc = read_env_var(&EnvVar::TwitterAcc);
    let tweets = twitter::user_timeline(&acc, delay_count).unwrap();
    let mut msg = format!("Showing last {} delays:\n\n", delay_count);
    for (i, tweet) in tweets.iter().enumerate() {
        msg += &format!("{}. {}\n", i + 1, tweet);
    }
    send(chat_id, &msg)?;
    Ok(())
}

fn respond_unknown(chat_id: i32) -> IronResult<()> {
    send(chat_id, "Unknown command. Try using /help")?;
    Ok(())
}
<commit_msg>Text optimization<commit_after>extern crate iron;
extern crate serde_json;
extern crate reqwest;
use self::iron::prelude::*;
use self::iron::{status, Request, Response, IronResult};

use util::{EnvVar, read_env_var};
use util::telegram::{register, unregister, send, send_with_reply_markup};
use util::twitter;
use model::telegram;

use std::io::Read;

pub fn telegram(req: &mut Request) -> IronResult<Response> {
    let mut body = String::new();
    req.body
        .read_to_string(&mut body)
        .map_err(|e| IronError::new(e, (status::BadRequest, "Error reading request")))?;
    let update: telegram::Update = serde_json::from_str(&body).unwrap();
    if let Some(msg) = update.message {
        if let Some(txt) = msg.text {
            let is_private = msg.chat.chat_type == "private";
            let identifier = format!("@{}", read_env_var(&EnvVar::Name));
            let has_identifier = txt.find(&identifier).is_some();
            let txt = strip_identifier(&txt);
            if is_private || has_identifier {
                let id = msg.chat.id;
                match txt.as_str() {
                    "/start" => respond_start(id),
                    "/help" => respond_help(id),
                    "/unsubscribe" => respond_unsubscribe(id),
                    "/delays" => respond_delays(id),
                    txt => {
                        if let Ok(num) = txt.parse::<u32>() {
                            respond_num_delays(id, num)
                        } else if is_private {
                            respond_unknown(id)
                        } else {
                            Ok(())
                        }
                    }
                }?;
            }
        }
    }
    Ok(Response::with((status::Ok, "ok")))
}

fn strip_identifier(msg: &str) -> String {
    let identifier = format!("@{}", read_env_var(&EnvVar::Name));
    let msg = if let Some(pos) = msg.find(&identifier) {
        let end = pos + identifier.len();
        msg[..pos].to_owned() + &msg[end..]
    } else {
        msg.to_owned()
    };
    msg.trim().to_owned()
}

fn respond_start(chat_id: i32) -> IronResult<()> {
    let new_registration = register(chat_id).unwrap();
    let msg = if new_registration {
        let acc = read_env_var(&EnvVar::TwitterAcc);
        let tweet = twitter::user_last_tweet(&acc).unwrap();
        format!("Successfully registered!\nLast delay:\n\n{}", tweet)
    } else {
        "This chat has already been registered".to_owned()
    };
    send(chat_id, &msg)?;
    Ok(())
}

fn respond_help(chat_id: i32) -> IronResult<()> {
    send(chat_id,
         "Available commands:\n\n\
        /start - Subscribes this chat to be notified of SBB delays\n\
        /unsubscribe - Unsubscribes this chat from the delay notifications\n\
        /delays - Shows the last `n` delays\n\
        /help - Shows this window")?;
    Ok(())
}

fn respond_unsubscribe(chat_id: i32) -> IronResult<()> {
    let unsubscribed = unregister(chat_id).unwrap();
    let msg = if unsubscribed {
        "Successfully unsubscribed from the delay notifications.\n\
        Use /start to subscribe again"
    } else {
        "This chat was not subscribed to be notified of delays in the first place, silly!\n\
        Use /start if you want to subscribe"
    };
    send(chat_id, msg)?;
    Ok(())
}

fn respond_delays(chat_id: i32) -> IronResult<()> {
    use model::telegram::{InlineKeyboardMarkup, InlineKeyboardButton};
    let mut buttons = Vec::new();
    let mut count = 1;
    for _ in 0..3 {
        let mut row = Vec::new();
        for _ in 0..3 {
            let count_str = format!("{}", count);
            let button = InlineKeyboardButton {
                text: count_str.clone(),
                switch_inline_query_current_chat: Some(count_str),
            };
            row.push(button);
            count += 1;
        }
        buttons.push(row);
    }
    let markup = InlineKeyboardMarkup { inline_keyboard: buttons };
    let msg = "How many of the last delays to you want to look up?";
    let mut s = String::new();
    send_with_reply_markup(chat_id, msg, Some(markup))?.read_to_string(&mut s).unwrap();
    Ok(())
}

fn respond_num_delays(chat_id: i32, delay_count: u32) -> IronResult<()> {
    const MIN: u32 = 1;
    const MAX: u32 = 9;
    if delay_count < MIN || delay_count > MAX {
        let msg = format!("Invalid number of delays selected, \
            please enter a number between {} and {}.",
                          MIN,
                          MAX);
        send(chat_id, &msg)?;
        return Ok(());
    }
    let acc = read_env_var(&EnvVar::TwitterAcc);
    let tweets = twitter::user_timeline(&acc, delay_count).unwrap();
    let mut msg = if delay_count == 1 {
        "Showing last delay:\n\n".to_owned()
    } else {
        format!("Showing last {} delays:\n\n", delay_count)
    };
    for (i, tweet) in tweets.iter().enumerate() {
        msg += &format!("{}. {}\n", i + 1, tweet);
    }
    send(chat_id, &msg)?;
    Ok(())
}

fn respond_unknown(chat_id: i32) -> IronResult<()> {
    send(chat_id, "Unknown command. Try using /help")?;
    Ok(())
}
<|endoftext|>


<commit_before>use fuzzy_matcher;
///! score is responsible for calculating the scores of the similarity between
///! the query and the choice.
use regex::Regex;

pub fn fuzzy_match(choice: &str, pattern: &str) -> Option<(i64, Vec<usize>)> {
    if pattern.is_empty() || choice.is_empty() {
        return Some((0, Vec::new()));
    }

    fuzzy_matcher::skim::fuzzy_indices(choice, pattern)
}

pub fn regex_match(choice: &str, pattern: &Option<Regex>) -> Option<(usize, usize)> {
    match *pattern {
        Some(ref pat) => {
            let mat = pat.find(choice)?;
            Some((mat.start(), mat.end()))
        }
        None => None,
    }
}

// Pattern may appear in sevearl places, return the first and last occurrence
pub fn exact_match(choice: &str, pattern: &str) -> Option<((usize, usize), (usize, usize))> {
    // search from the start
    let start_pos = choice.find(pattern)?;
    let first_occur = (start_pos, start_pos + pattern.len());
    let last_pos = choice.rfind(pattern)?;
    let last_occur = (last_pos, last_pos + pattern.len());
    Some((first_occur, last_occur))
}
<commit_msg>fix: wrong matches on empty lines<commit_after>use fuzzy_matcher;
///! score is responsible for calculating the scores of the similarity between
///! the query and the choice.
use regex::Regex;

pub fn fuzzy_match(choice: &str, pattern: &str) -> Option<(i64, Vec<usize>)> {
    if pattern.is_empty() {
        return Some((0, Vec::new()));
    } else if choice.is_empty() {
        return None;
    }

    fuzzy_matcher::skim::fuzzy_indices(choice, pattern)
}

pub fn regex_match(choice: &str, pattern: &Option<Regex>) -> Option<(usize, usize)> {
    match *pattern {
        Some(ref pat) => {
            let mat = pat.find(choice)?;
            Some((mat.start(), mat.end()))
        }
        None => None,
    }
}

// Pattern may appear in sevearl places, return the first and last occurrence
pub fn exact_match(choice: &str, pattern: &str) -> Option<((usize, usize), (usize, usize))> {
    // search from the start
    let start_pos = choice.find(pattern)?;
    let first_occur = (start_pos, start_pos + pattern.len());
    let last_pos = choice.rfind(pattern)?;
    let last_occur = (last_pos, last_pos + pattern.len());
    Some((first_occur, last_occur))
}
<|endoftext|>


<commit_before>use ast::Expr;
use ast::ExprType::*;
use ast::Program;
use ast::Stmt;
use ast::StmtType::*;
use ast::visit::Visitor;
use error::err;
use error::unimplemented;
use error::ErrorCode;
use error::ParseError;
use lexer::position::Position;
use parser::Parser;
use sym::Sym::*;
use sym::SymbolTable;

struct SemCheck<'a> {
    program: &'a Program,
    global: SymbolTable,
}

impl<'a> Visitor for SemCheck<'a> {
    type Returns = ();

    fn visit_stmt(&mut self, s: &Stmt) -> Result<(), ParseError> {
        match s.node {
            StmtReturn(ref expr) => {
                if expr.is_none() {
                    return err(s.pos, "no return value given".to_string(),
                        ErrorCode::ExpectedValue);
                }

                try!(self.visit_expr(&expr.as_ref().unwrap()));

                Ok(())
            }

            StmtBlock(ref stmts) => {
                for stmt in stmts {
                    try!(self.visit_stmt(stmt));
                }

                Ok(())
            }

            _ => unimplemented(s.pos)
        }
    }

    fn visit_expr(&mut self, e: &Expr) -> Result<(), ParseError> {
        match e.node {
            ExprLitInt(val) => {
                Ok(())
            }

            _ => unimplemented(e.pos)
        }
    }
}

impl<'a> SemCheck<'a> {
    pub fn new(prog: &Program) -> SemCheck {
        SemCheck { program: prog, global: SymbolTable::new() }
    }

    pub fn check(&mut self) -> Result<(), ParseError> {
        self.check_main()
    }

    fn check_main(&mut self) -> Result<(), ParseError> {
        let fct = self.program.function("main");

        if fct.is_none() {
            return err(Position::new(1, 1), "main not found".to_string(),
                ErrorCode::MainDefinition)
        }

        let fct = fct.unwrap();

        if !fct.type_params.empty() || fct.params.len() > 0 ||
            !fct.return_type.is_int() {
            return err(fct.position, "definition of main not correct".to_string(),
                ErrorCode::MainDefinition)
        }

        try!(self.visit_stmt(&fct.block));

        Ok(())
    }
}

#[cfg(test)]
fn ck(code: &'static str) -> Result<(), ParseError> {
    let prog = Parser::from_str(code).parse().unwrap();

    SemCheck::new(&prog).check()
}

#[test]
fn test_main_undefined() {
    assert!(ck("fn foo() {}").is_err());
}

#[test]
fn test_main_definition_invalid() {
    assert!(ck("fn main(x:int) {}").is_err());
}

#[test]
fn test_main_no_return_value() {
    assert!(ck("fn main() {}").is_err());
}

#[test]
fn test_main() {
    assert!(ck("fn main() -> int { return 0; }").is_ok());
}

<commit_msg>added function valid_main_definition<commit_after>use ast::Expr;
use ast::ExprType::*;
use ast::Function;
use ast::Program;
use ast::Stmt;
use ast::StmtType::*;
use ast::visit::Visitor;

use error::err;
use error::unimplemented;
use error::ErrorCode;
use error::ParseError;

use lexer::position::Position;

use parser::Parser;

use sym::Sym::*;
use sym::SymbolTable;

struct SemCheck<'a> {
    program: &'a Program,
    global: SymbolTable,
}

impl<'a> Visitor for SemCheck<'a> {
    type Returns = ();

    fn visit_stmt(&mut self, s: &Stmt) -> Result<(), ParseError> {
        match s.node {
            StmtReturn(ref expr) => {
                if expr.is_none() {
                    return err(s.pos, "no return value given".to_string(),
                        ErrorCode::ExpectedValue);
                }

                try!(self.visit_expr(&expr.as_ref().unwrap()));

                Ok(())
            }

            StmtBlock(ref stmts) => {
                for stmt in stmts {
                    try!(self.visit_stmt(stmt));
                }

                Ok(())
            }

            _ => unimplemented(s.pos)
        }
    }

    fn visit_expr(&mut self, e: &Expr) -> Result<(), ParseError> {
        match e.node {
            ExprLitInt(val) => {
                Ok(())
            }

            _ => unimplemented(e.pos)
        }
    }
}

impl<'a> SemCheck<'a> {
    pub fn new(prog: &Program) -> SemCheck {
        SemCheck { program: prog, global: SymbolTable::new() }
    }

    pub fn check(&mut self) -> Result<(), ParseError> {
        self.check_main()
    }

    fn check_main(&mut self) -> Result<(), ParseError> {
        let fct = self.program.function("main");

        if fct.is_none() {
            return err(Position::new(1, 1), "main not found".to_string(),
                ErrorCode::MainDefinition)
        }

        let fct = fct.unwrap();

        if !valid_main_definition(fct) {
            return err(fct.position, "definition of main not correct".to_string(),
                ErrorCode::MainDefinition)
        }

        try!(self.visit_stmt(&fct.block));

        Ok(())
    }
}

fn valid_main_definition(fct: &Function) -> bool {
    fct.type_params.empty() && fct.params.len() == 0 && fct.return_type.is_int()
}

#[cfg(test)]
fn ck(code: &'static str) -> Result<(), ParseError> {
    let prog = Parser::from_str(code).parse().unwrap();

    SemCheck::new(&prog).check()
}

#[test]
fn test_main_undefined() {
    assert!(ck("fn foo() {}").is_err());
}

#[test]
fn test_main_definition_invalid() {
    assert!(ck("fn main(x:int) {}").is_err());
}

#[test]
fn test_main_no_return_value() {
    assert!(ck("fn main() {}").is_err());
}

#[test]
fn test_main() {
    assert!(ck("fn main() -> int { return 0; }").is_ok());
}

<|endoftext|>


<commit_before>extern crate glm;

pub trait Shape {
    fn get_center(&self) -> glm::DVec2;
    fn contains(&self, point: &glm::DVec2) -> bool;
    fn intersects_with_circle(&self, circle: &Circle) -> bool;
    fn intersects_with_rectangle(&self, rectangle: &Rectangle) -> bool;
    fn distance<S>(&self, other: &S) -> f64
        where S: Shape
    {
        glm::distance(self.get_center(), other.get_center())
    }
}

pub struct Rectangle {
    dims: glm::DVec2,
    center: glm::DVec2,
}

impl Shape for Rectangle {
    fn get_center(&self) -> glm::DVec2 {
        self.center
    }

    fn contains(&self, point: &glm::DVec2) -> bool {
        let half_x = self.dims.x / 2.;
        let half_y = self.dims.y / 2.;

        if self.center.x - half_x > point.x {
            false
        } else if self.center.x + half_x < point.x {
            false
        } else if self.center.y - half_y > point.y {
            false
        } else if self.center.y + half_y < point.y {
            false
        } else {
            true
        }
    }

    fn intersects_with_rectangle(&self, rectangle: &Rectangle) -> bool {
        let half_x = self.dims.x / 2.;
        let half_y = self.dims.y / 2.;

        if self.center.x - half_x > rectangle.center.x + rectangle.dims.x / 2. {
            false
        } else if self.center.x + half_x < rectangle.center.x - rectangle.dims.x / 2. {
            false
        } else if self.center.y - half_y > rectangle.center.y + rectangle.dims.y / 2. {
            false
        } else if self.center.y + half_y < rectangle.center.y - rectangle.dims.y / 2. {
            false
        } else {
            true
        }
    }

    fn intersects_with_circle(&self, circle: &Circle) -> bool {
        circle.intersects_with_rectangle(&self)
    }
}

pub struct Circle {
    radius: f64,
    center: glm::DVec2,
}

impl Shape for Circle {
    fn get_center(&self) -> glm::DVec2 {
        self.center
    }

    fn contains(&self, point: &glm::DVec2) -> bool {
        let distance = glm::distance(self.center, *point);
        distance < self.radius
    }

    fn intersects_with_rectangle(&self, rectangle: &Rectangle) -> bool {
        false
    }

    fn intersects_with_circle(&self, circle: &Circle) -> bool {
        let distance = glm::distance(self.center, circle.center);
        distance < (self.radius + circle.radius)
    }
}

#[cfg(test)]
mod test {
    extern crate glm;
    use super::*;

    #[test]
    fn circle_no_contains() {
        let circle = Circle {
            radius: 1 as f64,
            center: glm::dvec2(2 as f64, 0 as f64),
        };
        let point = glm::dvec2(4 as f64, 4 as f64);
        assert!(!circle.contains(&point));
    }

    #[test]
    fn circle_contains() {
        let circle = Circle {
            radius: 3 as f64,
            center: glm::dvec2(2 as f64, 3 as f64),
        };
        let point = glm::dvec2(4 as f64, 4 as f64);
        assert!(circle.contains(&point));
    }

    #[test]
    fn circle_circle_no_intersect() {
        let circle_a = Circle {
            radius: 3 as f64,
            center: glm::dvec2(2 as f64, 3 as f64),
        };

        let circle_b = Circle {
            radius: 1 as f64,
            center: glm::dvec2(4 as f64, 7 as f64),
        };

        assert!(!circle_a.intersects_with_circle(&circle_b));
        assert!(!circle_b.intersects_with_circle(&circle_a));
    }

    #[test]
    fn circle_circle_intersect() {
        let circle_a = Circle {
            radius: 3 as f64,
            center: glm::dvec2(2 as f64, 3 as f64),
        };

        let circle_b = Circle {
            radius: 1 as f64,
            center: glm::dvec2(1 as f64, 5 as f64),
        };

        assert!(circle_a.intersects_with_circle(&circle_b));
        assert!(circle_b.intersects_with_circle(&circle_a));
    }

    #[test]
    fn rectangle_no_contains() {
        let rectangle = Rectangle {
            dims: glm::dvec2(2 as f64, 3 as f64),
            center: glm::dvec2(3 as f64, 0 as f64),
        };
        let point = glm::dvec2(3.5 as f64, -1 as f64);
        assert!(rectangle.contains(&point));
    }

    #[test]
    fn rectangle_contains() {
        let rectangle = Rectangle {
            dims: glm::dvec2(2 as f64, 3 as f64),
            center: glm::dvec2(3 as f64, 0 as f64),
        };
        let point = glm::dvec2(3.5 as f64, 2 as f64);
        assert!(!rectangle.contains(&point));
    }

    #[test]
    fn rectangle_rectangle_no_intersect() {
        let rectangle_a = Rectangle {
            dims: glm::dvec2(2 as f64, 3 as f64),
            center: glm::dvec2(3 as f64, 0 as f64),
        };

        let rectangle_b = Rectangle {
            dims: glm::dvec2(5 as f64, 2 as f64),
            center: glm::dvec2(0 as f64, 8 as f64),
        };
        assert!(!rectangle_a.intersects_with_rectangle(&rectangle_b));
        assert!(!rectangle_b.intersects_with_rectangle(&rectangle_a));
    }

    #[test]
    fn rectangle_rectangle_intersect() {
        let rectangle_a = Rectangle {
            dims: glm::dvec2(2 as f64, 3 as f64),
            center: glm::dvec2(3 as f64, 0 as f64),
        };

        let rectangle_b = Rectangle {
            dims: glm::dvec2(1 as f64, 2 as f64),
            center: glm::dvec2(2.5 as f64, 1 as f64),
        };
        assert!(rectangle_a.intersects_with_rectangle(&rectangle_b));
        assert!(rectangle_b.intersects_with_rectangle(&rectangle_a));
    }
}
<commit_msg>rectangle and circle intersect if the center of either is inside the other<commit_after>extern crate glm;

pub trait Shape {
    fn get_center(&self) -> glm::DVec2;
    fn contains(&self, point: &glm::DVec2) -> bool;
    fn intersects_with_circle(&self, circle: &Circle) -> bool;
    fn intersects_with_rectangle(&self, rectangle: &Rectangle) -> bool;
    fn distance<S>(&self, other: &S) -> f64
        where S: Shape
    {
        glm::distance(self.get_center(), other.get_center())
    }
}

pub struct Rectangle {
    dims: glm::DVec2,
    center: glm::DVec2,
}

impl Shape for Rectangle {
    fn get_center(&self) -> glm::DVec2 {
        self.center
    }

    fn contains(&self, point: &glm::DVec2) -> bool {
        let half_x = self.dims.x / 2.;
        let half_y = self.dims.y / 2.;

        if self.center.x - half_x > point.x {
            false
        } else if self.center.x + half_x < point.x {
            false
        } else if self.center.y - half_y > point.y {
            false
        } else if self.center.y + half_y < point.y {
            false
        } else {
            true
        }
    }

    fn intersects_with_rectangle(&self, rectangle: &Rectangle) -> bool {
        let half_x = self.dims.x / 2.;
        let half_y = self.dims.y / 2.;

        if self.center.x - half_x > rectangle.center.x + rectangle.dims.x / 2. {
            false
        } else if self.center.x + half_x < rectangle.center.x - rectangle.dims.x / 2. {
            false
        } else if self.center.y - half_y > rectangle.center.y + rectangle.dims.y / 2. {
            false
        } else if self.center.y + half_y < rectangle.center.y - rectangle.dims.y / 2. {
            false
        } else {
            true
        }
    }

    fn intersects_with_circle(&self, circle: &Circle) -> bool {
        circle.intersects_with_rectangle(&self)
    }
}

pub struct Circle {
    radius: f64,
    center: glm::DVec2,
}

impl Shape for Circle {
    fn get_center(&self) -> glm::DVec2 {
        self.center
    }

    fn contains(&self, point: &glm::DVec2) -> bool {
        let distance = glm::distance(self.center, *point);
        distance < self.radius
    }

    fn intersects_with_rectangle(&self, rectangle: &Rectangle) -> bool {
        if self.contains(&rectangle.center) {
            true
        } else if rectangle.contains(&self.center) {
            true
        } else {
            false
        }
    }

    fn intersects_with_circle(&self, circle: &Circle) -> bool {
        let distance = glm::distance(self.center, circle.center);
        distance < (self.radius + circle.radius)
    }
}

#[cfg(test)]
mod test {
    extern crate glm;
    use super::*;

    #[test]
    fn circle_no_contains() {
        let circle = Circle {
            radius: 1 as f64,
            center: glm::dvec2(2 as f64, 0 as f64),
        };
        let point = glm::dvec2(4 as f64, 4 as f64);
        assert!(!circle.contains(&point));
    }

    #[test]
    fn circle_contains() {
        let circle = Circle {
            radius: 3 as f64,
            center: glm::dvec2(2 as f64, 3 as f64),
        };
        let point = glm::dvec2(4 as f64, 4 as f64);
        assert!(circle.contains(&point));
    }

    #[test]
    fn circle_circle_no_intersect() {
        let circle_a = Circle {
            radius: 3 as f64,
            center: glm::dvec2(2 as f64, 3 as f64),
        };

        let circle_b = Circle {
            radius: 1 as f64,
            center: glm::dvec2(4 as f64, 7 as f64),
        };

        assert!(!circle_a.intersects_with_circle(&circle_b));
        assert!(!circle_b.intersects_with_circle(&circle_a));
    }

    #[test]
    fn circle_circle_intersect() {
        let circle_a = Circle {
            radius: 3 as f64,
            center: glm::dvec2(2 as f64, 3 as f64),
        };

        let circle_b = Circle {
            radius: 1 as f64,
            center: glm::dvec2(1 as f64, 5 as f64),
        };

        assert!(circle_a.intersects_with_circle(&circle_b));
        assert!(circle_b.intersects_with_circle(&circle_a));
    }

    #[test]
    fn rectangle_no_contains() {
        let rectangle = Rectangle {
            dims: glm::dvec2(2 as f64, 3 as f64),
            center: glm::dvec2(3 as f64, 0 as f64),
        };
        let point = glm::dvec2(3.5 as f64, -1 as f64);
        assert!(rectangle.contains(&point));
    }

    #[test]
    fn rectangle_contains() {
        let rectangle = Rectangle {
            dims: glm::dvec2(2 as f64, 3 as f64),
            center: glm::dvec2(3 as f64, 0 as f64),
        };
        let point = glm::dvec2(3.5 as f64, 2 as f64);
        assert!(!rectangle.contains(&point));
    }

    #[test]
    fn rectangle_rectangle_no_intersect() {
        let rectangle_a = Rectangle {
            dims: glm::dvec2(2 as f64, 3 as f64),
            center: glm::dvec2(3 as f64, 0 as f64),
        };

        let rectangle_b = Rectangle {
            dims: glm::dvec2(5 as f64, 2 as f64),
            center: glm::dvec2(0 as f64, 8 as f64),
        };
        assert!(!rectangle_a.intersects_with_rectangle(&rectangle_b));
        assert!(!rectangle_b.intersects_with_rectangle(&rectangle_a));
    }

    #[test]
    fn rectangle_rectangle_intersect() {
        let rectangle_a = Rectangle {
            dims: glm::dvec2(2 as f64, 3 as f64),
            center: glm::dvec2(3 as f64, 0 as f64),
        };

        let rectangle_b = Rectangle {
            dims: glm::dvec2(1 as f64, 2 as f64),
            center: glm::dvec2(2.5 as f64, 1 as f64),
        };
        assert!(rectangle_a.intersects_with_rectangle(&rectangle_b));
        assert!(rectangle_b.intersects_with_rectangle(&rectangle_a));
    }

    #[test]
    fn rectangle_circle_no_intersect() {
        let rectangle = Rectangle {
            dims: glm::dvec2(5 as f64, 2 as f64),
            center: glm::dvec2(6 as f64, 0 as f64),
        };

        let circle = Circle {
            radius: 3 as f64,
            center: glm::dvec2(2 as f64, 3 as f64),
        };

        assert!(!rectangle.intersects_with_circle(&circle));
        assert!(!circle.intersects_with_rectangle(&rectangle));
    }

    #[test]
    fn rectangle_inside_circle() {
        let rectangle = Rectangle {
            dims: glm::dvec2(1 as f64, 2 as f64),
            center: glm::dvec2(3 as f64, 5 as f64),
        };

        let circle = Circle {
            radius: 5 as f64,
            center: glm::dvec2(2 as f64, 3 as f64),
        };

        assert!(rectangle.intersects_with_circle(&circle));
        assert!(circle.intersects_with_rectangle(&rectangle));
    }

    #[test]
    fn circle_inside_rectangle() {
        let rectangle = Rectangle {
            dims: glm::dvec2(5 as f64, 7 as f64),
            center: glm::dvec2(4 as f64, 2 as f64),
        };

        let circle = Circle {
            radius: 1 as f64,
            center: glm::dvec2(5 as f64, 3 as f64),
        };

        assert!(rectangle.intersects_with_circle(&circle));
        assert!(circle.intersects_with_rectangle(&rectangle));
    }
}
<|endoftext|>


<commit_before>use std::process::{Command, Output};
use std::io::Error;
use configuration;
use output;
use file;

pub fn provision(configuration: &configuration::Configuration) -> i32 {

    let mut packages = Vec::new();

    packages.extend(configuration.packages.iter().cloned());

    packages.reverse();

    let mut exit_codes = Vec::new();

    let package_exit_codes = install_packages(&packages);
    exit_codes.extend(&package_exit_codes[..]);

    let results = handle_file_resources(&configuration.files);
    exit_codes.extend(&results[..]);

    exit_codes.sort();

    match exit_codes.last() {
        Some(&0) => return 0,
        None     => return 0,
        _        => return 1
    }
}

fn install_packages(package_list: &Vec<String>) -> Vec<i32> {
    let mut exit_codes = Vec::new();
    let mut packages = package_list.clone();

    while let Some(package) = packages.pop() {
        if is_package_installed(&package) {
            continue;
        }
        let shellout = install_package(&package);
        output::print_shellout::<String>(&package, &shellout);
        let exit_status = shellout.status.clone();
        if exit_status.success() == false {
            exit_codes.push(exit_status.code().unwrap());
        }
    }
    exit_codes
}

fn handle_file_resources(resources: &Vec<file::FileResource>) -> Vec<i32> {
    let mut results = Vec::new();
    for resource in resources {
        let result = resource.write_file();
        match result {
            Ok(_) =>  {
                let msg = format!("==> Wrote file {}", resource.path);
                output::print_message(msg, output::MessageType::Stdout);
                results.push(0);
            },
            Err(err) => {
                let msg = format!("==> Error while writing file {}", resource.path);
                output::print_message(msg, output::MessageType::Stderr);
                output::print_message(format!("==> {}", err), output::MessageType::Stderr);
                results.push(1);
            }
        }
    }
    results
}

fn is_package_installed(package_name: &String) -> bool {
    let command_str = format!("yum list installed {}", package_name);
    let output = Command::new(command_str).output();
    output.is_ok()
}

fn install_package(package: &String) -> Output {
    Command::new("sudo")
        .args(&vec!["yum", "install", "-y", package])
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) })
}
<commit_msg>Only unwrap result, do not panic if package install fails<commit_after>use std::process::{Command, Output};
use std::io::Error;
use configuration;
use output;
use file;

pub fn provision(configuration: &configuration::Configuration) -> i32 {

    let mut packages = Vec::new();

    packages.extend(configuration.packages.iter().cloned());

    packages.reverse();

    let mut exit_codes = Vec::new();

    let package_exit_codes = install_packages(&packages);
    exit_codes.extend(&package_exit_codes[..]);

    let results = handle_file_resources(&configuration.files);
    exit_codes.extend(&results[..]);

    exit_codes.sort();

    match exit_codes.last() {
        Some(&0) => return 0,
        None     => return 0,
        _        => return 1
    }
}

fn install_packages(package_list: &Vec<String>) -> Vec<i32> {
    let mut exit_codes = Vec::new();
    let mut packages = package_list.clone();

    while let Some(package) = packages.pop() {
        if is_package_installed(&package) {
            continue;
        }
        let shellout = install_package(&package);
        output::print_shellout::<String>(&package, &shellout);
        let exit_status = shellout.status.clone();
        if exit_status.success() == false {
            exit_codes.push(exit_status.code().unwrap());
        }
    }
    exit_codes
}

fn handle_file_resources(resources: &Vec<file::FileResource>) -> Vec<i32> {
    let mut results = Vec::new();
    for resource in resources {
        let result = resource.write_file();
        match result {
            Ok(_) =>  {
                let msg = format!("==> Wrote file {}", resource.path);
                output::print_message(msg, output::MessageType::Stdout);
                results.push(0);
            },
            Err(err) => {
                let msg = format!("==> Error while writing file {}", resource.path);
                output::print_message(msg, output::MessageType::Stderr);
                output::print_message(format!("==> {}", err), output::MessageType::Stderr);
                results.push(1);
            }
        }
    }
    results
}

fn is_package_installed(package_name: &String) -> bool {
    let command_str = format!("yum list installed {}", package_name);
    let output = Command::new(command_str).output();
    output.is_ok()
}

fn install_package(package: &String) -> Output {
    Command::new("sudo")
        .args(&vec!["yum", "install", "-y", package])
        .output()
        .unwrap()
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate process_execution;

use clap::{App, AppSettings, Arg};
use std::process::exit;
use std::collections::BTreeMap;

use std::iter::Iterator;

/// A binary which takes args of format:
///  process_executor --env=FOO=bar --env=SOME=value -- /path/to/binary --flag --otherflag
/// and runs /path/to/binary --flag --otherflag with FOO and SOME set.
/// It outputs its output/err to stdout/err, and exits with its exit code.
///
/// It does not perform $PATH lookup or shell expansion.
fn main() {
  let args = App::new("process_executor")
    .arg(
      Arg::with_name("server")
        .long("server")
        .takes_value(true)
        .help(
          "The host:port of the gRPC server to connect to. Forces remote execution. \
If unspecified, local execution will be performed.",
        ),
    )
    .arg(
      Arg::with_name("env")
        .long("env")
        .takes_value(true)
        .multiple(true)
        .help(
          "Environment variables with which the process should be run.",
        ),
    )
    .setting(AppSettings::TrailingVarArg)
    .arg(Arg::with_name("argv").multiple(true).last(true).required(
      true,
    ))
    .get_matches();

  let argv: Vec<String> = args
    .values_of("argv")
    .unwrap()
    .map(|v| v.to_string())
    .collect();
  let env: BTreeMap<String, String> = args
    .values_of("env")
    .unwrap()
    .map(|v| {
      let mut parts = v.splitn(2, "=");
      (
        parts.next().unwrap().to_string(),
        parts.next().unwrap_or_default().to_string(),
      )
    })
    .collect();
  let server = args.value_of("server");

  let request = process_execution::ExecuteProcessRequest { argv, env };
  let result = match server {
    Some(addr) => {
      process_execution::remote::CommandRunner::new(addr, 1)
        .run_command_remote(request)
        .unwrap()
    }
    None => process_execution::local::run_command_locally(request).unwrap(),
  };
  print!("{}", String::from_utf8(result.stdout).unwrap());
  eprint!("{}", String::from_utf8(result.stderr).unwrap());
  exit(result.exit_code);
}
<commit_msg>Process executor does not require env flag to be set (#5409)<commit_after>extern crate clap;
extern crate process_execution;

use clap::{App, AppSettings, Arg};
use std::process::exit;
use std::collections::BTreeMap;

use std::iter::Iterator;

/// A binary which takes args of format:
///  process_executor --env=FOO=bar --env=SOME=value -- /path/to/binary --flag --otherflag
/// and runs /path/to/binary --flag --otherflag with FOO and SOME set.
/// It outputs its output/err to stdout/err, and exits with its exit code.
///
/// It does not perform $PATH lookup or shell expansion.
fn main() {
  let args = App::new("process_executor")
    .arg(
      Arg::with_name("server")
        .long("server")
        .takes_value(true)
        .help(
          "The host:port of the gRPC server to connect to. Forces remote execution. \
If unspecified, local execution will be performed.",
        ),
    )
    .arg(
      Arg::with_name("env")
        .long("env")
        .takes_value(true)
        .multiple(true)
        .help(
          "Environment variables with which the process should be run.",
        ),
    )
    .setting(AppSettings::TrailingVarArg)
    .arg(Arg::with_name("argv").multiple(true).last(true).required(
      true,
    ))
    .get_matches();

  let argv: Vec<String> = args
    .values_of("argv")
    .unwrap()
    .map(|v| v.to_string())
    .collect();
  let env: BTreeMap<String, String> = match args.values_of("env") {
    Some(values) => {
      values
        .map(|v| {
          let mut parts = v.splitn(2, "=");
          (
            parts.next().unwrap().to_string(),
            parts.next().unwrap_or_default().to_string(),
          )
        })
        .collect()
    }
    None => BTreeMap::new(),
  };
  let server = args.value_of("server");

  let request = process_execution::ExecuteProcessRequest { argv, env };
  let result = match server {
    Some(addr) => {
      process_execution::remote::CommandRunner::new(addr, 1)
        .run_command_remote(request)
        .unwrap()
    }
    None => process_execution::local::run_command_locally(request).unwrap(),
  };
  print!("{}", String::from_utf8(result.stdout).unwrap());
  eprint!("{}", String::from_utf8(result.stderr).unwrap());
  exit(result.exit_code);
}
<|endoftext|>


<commit_before>use std::mem::size_of;

use super::*;

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub(crate) struct Node {
    pub(crate) data: Data,
    pub(crate) next: Option<PageId>,
    pub(crate) lo: IVec,
    pub(crate) hi: IVec,
    pub(crate) merging_child: Option<PageId>,
    pub(crate) merging: bool,
}

impl Node {
    #[inline]
    pub(crate) fn size_in_bytes(&self) -> u64 {
        let self_sz = size_of::<Self>() as u64;
        let lo_sz = self.lo.size_in_bytes();
        let hi_sz = self.hi.size_in_bytes();
        let data_sz = self.data.size_in_bytes();

        self_sz
            .saturating_add(lo_sz)
            .saturating_add(hi_sz)
            .saturating_add(data_sz)
    }

    pub(crate) fn apply(&mut self, frag: &Frag, merge_operator: Option<usize>) {
        use self::Frag::*;

        match *frag {
            Set(ref k, ref v) => {
                // (when hi is empty, it means it's unbounded)
                if self.hi.is_empty()
                    || prefix_cmp_encoded(k, &self.hi, &self.lo)
                        == std::cmp::Ordering::Less
                {
                    self.set_leaf(k.clone(), v.clone());
                } else {
                    panic!("tried to consolidate set at key <= hi")
                }
            }
            Merge(ref k, ref v) => {
                // (when hi is empty, it means it's unbounded)
                if self.hi.is_empty()
                    || prefix_cmp_encoded(k, &self.hi, &self.lo)
                        == std::cmp::Ordering::Less
                {
                    let merge_fn_ptr =
                        merge_operator.expect("must have a merge operator set");
                    unsafe {
                        let merge_fn: MergeOperator =
                            std::mem::transmute(merge_fn_ptr);
                        self.merge_leaf(k.clone(), v.clone(), merge_fn);
                    }
                } else {
                    panic!("tried to consolidate set at key <= hi")
                }
            }
            ChildSplit(ref child_split) => {
                self.child_split(child_split);
            }
            ParentSplit(ref parent_split) => {
                self.parent_split(parent_split);
            }
            Del(ref k) => {
                // (when hi is empty, it means it's unbounded)
                if self.hi.is_empty()
                    || prefix_cmp_encoded(k, &self.hi, &self.lo)
                        == std::cmp::Ordering::Less
                {
                    self.del_leaf(k);
                } else {
                    panic!("tried to consolidate del at key <= hi")
                }
            }
            Base(_) => panic!("encountered base page in middle of chain"),
            ParentMergeIntention(_pid) => unimplemented!(),
            ParentMergeConfirm => unimplemented!(),
            ChildMergeCap => unimplemented!(),
        }
    }

    pub(crate) fn set_leaf(&mut self, key: IVec, val: IVec) {
        if let Data::Leaf(ref mut records) = self.data {
            let search = records.binary_search_by(|(k, _)| prefix_cmp(k, &key));
            match search {
                Ok(idx) => records[idx] = (key, val),
                Err(idx) => records.insert(idx, (key, val)),
            }
        } else {
            panic!("tried to Set a value to an index");
        }
    }

    pub(crate) fn merge_leaf(
        &mut self,
        key: IVec,
        val: IVec,
        merge_fn: MergeOperator,
    ) {
        if let Data::Leaf(ref mut records) = self.data {
            let search = records.binary_search_by(|(k, _)| prefix_cmp(k, &key));

            let decoded_k = prefix_decode(&self.lo, &key);

            match search {
                Ok(idx) => {
                    let new =
                        merge_fn(&*decoded_k, Some(&records[idx].1), &val);
                    if let Some(new) = new {
                        records[idx] = (key, new.into());
                    } else {
                        records.remove(idx);
                    }
                }
                Err(idx) => {
                    let new = merge_fn(&*decoded_k, None, &val);
                    if let Some(new) = new {
                        records.insert(idx, (key, new.into()));
                    }
                }
            }
        } else {
            panic!("tried to Merge a value to an index");
        }
    }

    pub(crate) fn child_split(&mut self, cs: &ChildSplit) {
        self.data.drop_gte(&cs.at, &self.lo);
        self.hi = cs.at.clone();
        self.next = Some(cs.to);
    }

    pub(crate) fn parent_split(&mut self, ps: &ParentSplit) {
        if let Data::Index(ref mut ptrs) = self.data {
            let encoded_sep = prefix_encode(&self.lo, &ps.at);
            match ptrs.binary_search_by(|a| prefix_cmp(&a.0, &encoded_sep)) {
                Ok(_) => panic!("must not have found ptr"),
                Err(idx) => ptrs.insert(idx, (encoded_sep, ps.to)),
            }
        } else {
            panic!("tried to attach a ParentSplit to a Leaf chain");
        }
    }

    pub(crate) fn del_leaf(&mut self, key: &IVec) {
        if let Data::Leaf(ref mut records) = self.data {
            let search = records
                .binary_search_by(|&(ref k, ref _v)| prefix_cmp(k, &*key));
            if let Ok(idx) = search {
                records.remove(idx);
            }
        } else {
            panic!("tried to attach a Del to an Index chain");
        }
    }

    pub(crate) fn should_split(&self, max_sz: u64) -> bool {
        self.data.len() > 2 && self.size_in_bytes() > max_sz && self.merging_child.is_none() && !self.merging
    }

    pub(crate) fn should_merge(&self, min_sz: u64) -> bool {
        self.size_in_bytes() < min_sz && self.merging_child.is_none() && !self.merging
    }

    pub(crate) fn split(&self) -> Node {
        let (split, right_data) = self.data.split(&self.lo);
        Node {
            data: right_data,
            next: self.next,
            lo: split,
            hi: self.hi.clone(),
            merging_child: None,
            merging: false,
        }
    }

    pub(crate) fn receive_merge(&self, rhs: &Node) -> Node {
        let mut merged = self.clone();
        merged.hi = rhs.hi.clone();
        merged.data.receive_merge(rhs.lo.as_ref(), merged.lo.as_ref(), &rhs.data);
        merged
    }
}
<commit_msg>Implementing frag apply for merge<commit_after>use std::mem::size_of;

use super::*;

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub(crate) struct Node {
    pub(crate) data: Data,
    pub(crate) next: Option<PageId>,
    pub(crate) lo: IVec,
    pub(crate) hi: IVec,
    pub(crate) merging_child: Option<PageId>,
    pub(crate) merging: bool,
}

impl Node {
    #[inline]
    pub(crate) fn size_in_bytes(&self) -> u64 {
        let self_sz = size_of::<Self>() as u64;
        let lo_sz = self.lo.size_in_bytes();
        let hi_sz = self.hi.size_in_bytes();
        let data_sz = self.data.size_in_bytes();

        self_sz
            .saturating_add(lo_sz)
            .saturating_add(hi_sz)
            .saturating_add(data_sz)
    }

    pub(crate) fn apply(&mut self, frag: &Frag, merge_operator: Option<usize>) {
        use self::Frag::*;

        match *frag {
            Set(ref k, ref v) => {
                // (when hi is empty, it means it's unbounded)
                if self.hi.is_empty()
                    || prefix_cmp_encoded(k, &self.hi, &self.lo)
                        == std::cmp::Ordering::Less
                {
                    self.set_leaf(k.clone(), v.clone());
                } else {
                    panic!("tried to consolidate set at key <= hi")
                }
            }
            Merge(ref k, ref v) => {
                // (when hi is empty, it means it's unbounded)
                if self.hi.is_empty()
                    || prefix_cmp_encoded(k, &self.hi, &self.lo)
                        == std::cmp::Ordering::Less
                {
                    let merge_fn_ptr =
                        merge_operator.expect("must have a merge operator set");
                    unsafe {
                        let merge_fn: MergeOperator =
                            std::mem::transmute(merge_fn_ptr);
                        self.merge_leaf(k.clone(), v.clone(), merge_fn);
                    }
                } else {
                    panic!("tried to consolidate set at key <= hi")
                }
            }
            ChildSplit(ref child_split) => {
                self.child_split(child_split);
            }
            ParentSplit(ref parent_split) => {
                self.parent_split(parent_split);
            }
            Del(ref k) => {
                // (when hi is empty, it means it's unbounded)
                if self.hi.is_empty()
                    || prefix_cmp_encoded(k, &self.hi, &self.lo)
                        == std::cmp::Ordering::Less
                {
                    self.del_leaf(k);
                } else {
                    panic!("tried to consolidate del at key <= hi")
                }
            }
            Base(_) => panic!("encountered base page in middle of chain"),
            ParentMergeIntention(pid) => {
                assert!(self.merging_child.is_none());
                self.merging_child = Some(pid);
            }
            ParentMergeConfirm => {
                assert!(self.merging_child.is_some());
                self.merging_child = None;
            },
            ChildMergeCap => {
                assert!(!self.merging);
                self.merging = true;
            },
        }
    }

    pub(crate) fn set_leaf(&mut self, key: IVec, val: IVec) {
        if let Data::Leaf(ref mut records) = self.data {
            let search = records.binary_search_by(|(k, _)| prefix_cmp(k, &key));
            match search {
                Ok(idx) => records[idx] = (key, val),
                Err(idx) => records.insert(idx, (key, val)),
            }
        } else {
            panic!("tried to Set a value to an index");
        }
    }

    pub(crate) fn merge_leaf(
        &mut self,
        key: IVec,
        val: IVec,
        merge_fn: MergeOperator,
    ) {
        if let Data::Leaf(ref mut records) = self.data {
            let search = records.binary_search_by(|(k, _)| prefix_cmp(k, &key));

            let decoded_k = prefix_decode(&self.lo, &key);

            match search {
                Ok(idx) => {
                    let new =
                        merge_fn(&*decoded_k, Some(&records[idx].1), &val);
                    if let Some(new) = new {
                        records[idx] = (key, new.into());
                    } else {
                        records.remove(idx);
                    }
                }
                Err(idx) => {
                    let new = merge_fn(&*decoded_k, None, &val);
                    if let Some(new) = new {
                        records.insert(idx, (key, new.into()));
                    }
                }
            }
        } else {
            panic!("tried to Merge a value to an index");
        }
    }

    pub(crate) fn child_split(&mut self, cs: &ChildSplit) {
        self.data.drop_gte(&cs.at, &self.lo);
        self.hi = cs.at.clone();
        self.next = Some(cs.to);
    }

    pub(crate) fn parent_split(&mut self, ps: &ParentSplit) {
        if let Data::Index(ref mut ptrs) = self.data {
            let encoded_sep = prefix_encode(&self.lo, &ps.at);
            match ptrs.binary_search_by(|a| prefix_cmp(&a.0, &encoded_sep)) {
                Ok(_) => panic!("must not have found ptr"),
                Err(idx) => ptrs.insert(idx, (encoded_sep, ps.to)),
            }
        } else {
            panic!("tried to attach a ParentSplit to a Leaf chain");
        }
    }

    pub(crate) fn del_leaf(&mut self, key: &IVec) {
        if let Data::Leaf(ref mut records) = self.data {
            let search = records
                .binary_search_by(|&(ref k, ref _v)| prefix_cmp(k, &*key));
            if let Ok(idx) = search {
                records.remove(idx);
            }
        } else {
            panic!("tried to attach a Del to an Index chain");
        }
    }

    pub(crate) fn should_split(&self, max_sz: u64) -> bool {
        self.data.len() > 2 && self.size_in_bytes() > max_sz && self.merging_child.is_none() && !self.merging
    }

    pub(crate) fn should_merge(&self, min_sz: u64) -> bool {
        self.size_in_bytes() < min_sz && self.merging_child.is_none() && !self.merging
    }

    pub(crate) fn split(&self) -> Node {
        let (split, right_data) = self.data.split(&self.lo);
        Node {
            data: right_data,
            next: self.next,
            lo: split,
            hi: self.hi.clone(),
            merging_child: None,
            merging: false,
        }
    }

    pub(crate) fn receive_merge(&self, rhs: &Node) -> Node {
        let mut merged = self.clone();
        merged.hi = rhs.hi.clone();
        merged.data.receive_merge(rhs.lo.as_ref(), merged.lo.as_ref(), &rhs.data);
        merged
    }
}
<|endoftext|>


<commit_before>//use super::rocket;
//use rocket::local::Client;
//use rocket::http::Status;
//
//#[test]
//fn db_test() {
//    let client = Client::new(rocket()).expect("valid rocket instance");
//    let mut response = client.get("/db").dispatch();
//
//    assert_eq!(response.status(), Status::Ok);
//    assert_eq!(response.body_string(), Some("This Guy".into()));
//}
<commit_msg>Tests for db connection and session<commit_after>use super::rocket;
use rocket::local::Client;
use rocket::http::Status;
use diesel::prelude::*;
use schema::preferences::dsl::*;

#[test]
/// Tests connection to the database through the pool managed by rocket.
fn db_connection() {
    let conn = rocket().1;

    let expected_keys = vec!["session-key"];
    let actual_keys: Vec<String> = preferences.select(key).load(&*conn).unwrap();

    assert_eq!(expected_keys, actual_keys);
}

#[test]
/// Tests the response of the /session request is of length 24.
fn session() {
    let client = Client::new(rocket().0).expect("valid rocket instance");
    let mut response = client.get("/session").dispatch();

    assert_eq!(response.status(), Status::Ok);
    assert_eq!(response.body_string().unwrap().len(), 24);
}

#[test]
/// Compares the session hash in the database to the one returned by /session
fn session_hash() {
    let (rocket, conn) = rocket();
    let client = Client::new(rocket).expect("valid rocket instance");
    let mut response = client.get("/session").dispatch();

    let session_key: Vec<String> = preferences
        .filter(key.eq("session-key"))
        .select(value)
        .load(&*conn)
        .unwrap();

    assert_eq!(response.status(), Status::Ok);
    assert_eq!(response.body_string().unwrap(), session_key[0]);
}
<|endoftext|>


<commit_before>// Copyright 2021 Chad Williamson <chad@dahc.us>
//
// Use of this source code is governed by an MIT-syle license that can be
// found in the LICENSE file or at https://opensource.org/licenses/MIT.

// This file contains integration tests for the find command.
//
// Note: the `serial` macro is used on tests that make assumptions about the
// working directory, since we have at least one test that needs to change it.

use assert_cmd::Command;
use predicates::prelude::*;
use serial_test::serial;
use std::env;
use std::fs::File;
use tempdir::TempDir;

#[serial(working_dir)]
#[test]
fn no_args() {
    Command::cargo_bin("find")
        .expect("found binary")
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::contains("test_data"));
}

#[serial(working_dir)]
#[test]
fn two_matchers_both_match() {
    Command::cargo_bin("find")
        .expect("found binary")
        .args(&["-type", "d", "-name", "test_data"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::contains("test_data"));
}

#[serial(working_dir)]
#[test]
fn two_matchers_one_matches() {
    Command::cargo_bin("find")
        .expect("found binary")
        .args(&["-type", "f", "-name", "test_data"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::is_empty());
}

#[test]
fn matcher_with_side_effects_at_end() {
    let temp_dir = TempDir::new("find_cmd_").expect("made temp dir");
    let temp_dir_path = temp_dir.path().to_string_lossy();
    let test_file = temp_dir.path().join("test");
    File::create(&test_file).expect("created test file");

    Command::cargo_bin("find")
        .expect("found binary")
        .args(&[&temp_dir_path, "-name", "test", "-delete"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::is_empty());

    assert!(!test_file.exists(), "test file should be deleted");
    assert!(temp_dir.path().exists(), "temp dir should NOT be deleted");
}

#[test]
fn matcher_with_side_effects_in_front() {
    let temp_dir = TempDir::new("find_cmd_").expect("made temp dir");
    let temp_dir_path = temp_dir.path().to_string_lossy();
    let test_file = temp_dir.path().join("test");
    File::create(&test_file).expect("created test file");

    Command::cargo_bin("find")
        .expect("found binary")
        .args(&[&temp_dir_path, "-delete", "-name", "test"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::is_empty());

    assert!(!test_file.exists(), "test file should be deleted");
    assert!(!temp_dir.path().exists(), "temp dir should also be deleted");
}

// This could be covered by a unit test in principle... in practice, changing
// the working dir can't be done safely in unit tests unless `--test-threads=1`
// or `serial` goes everywhere, and it doesn't seem possible to get an
// appropriate `walkdir::DirEntry` for "." without actually changing dirs
// (or risking deletion of the repo itself).
#[serial(working_dir)]
#[test]
fn delete_on_dot_dir() {
    let temp_dir = TempDir::new("find_cmd_").expect("made temp dir");
    let original_dir = env::current_dir().unwrap();
    env::set_current_dir(&temp_dir.path()).expect("working dir changed");

    // "." should be matched (confirmed by the print), but not deleted.
    Command::cargo_bin("find")
        .expect("found binary")
        .args(&[".", "-delete", "-print"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::similar(".\n"));

    env::set_current_dir(original_dir).expect("restored original working dir");

    assert!(temp_dir.path().exists(), "temp dir should still exist");
}
<commit_msg>predicate: adjust the api<commit_after>// Copyright 2021 Chad Williamson <chad@dahc.us>
//
// Use of this source code is governed by an MIT-syle license that can be
// found in the LICENSE file or at https://opensource.org/licenses/MIT.

// This file contains integration tests for the find command.
//
// Note: the `serial` macro is used on tests that make assumptions about the
// working directory, since we have at least one test that needs to change it.

use assert_cmd::Command;
use predicates::prelude::*;
use serial_test::serial;
use std::env;
use std::fs::File;
use tempdir::TempDir;

#[serial(working_dir)]
#[test]
fn no_args() {
    Command::cargo_bin("find")
        .expect("found binary")
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::contains("test_data"));
}

#[serial(working_dir)]
#[test]
fn two_matchers_both_match() {
    Command::cargo_bin("find")
        .expect("found binary")
        .args(&["-type", "d", "-name", "test_data"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::contains("test_data"));
}

#[serial(working_dir)]
#[test]
fn two_matchers_one_matches() {
    Command::cargo_bin("find")
        .expect("found binary")
        .args(&["-type", "f", "-name", "test_data"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::is_empty());
}

#[test]
fn matcher_with_side_effects_at_end() {
    let temp_dir = TempDir::new("find_cmd_").expect("made temp dir");
    let temp_dir_path = temp_dir.path().to_string_lossy();
    let test_file = temp_dir.path().join("test");
    File::create(&test_file).expect("created test file");

    Command::cargo_bin("find")
        .expect("found binary")
        .args(&[&temp_dir_path, "-name", "test", "-delete"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::is_empty());

    assert!(!test_file.exists(), "test file should be deleted");
    assert!(temp_dir.path().exists(), "temp dir should NOT be deleted");
}

#[test]
fn matcher_with_side_effects_in_front() {
    let temp_dir = TempDir::new("find_cmd_").expect("made temp dir");
    let temp_dir_path = temp_dir.path().to_string_lossy();
    let test_file = temp_dir.path().join("test");
    File::create(&test_file).expect("created test file");

    Command::cargo_bin("find")
        .expect("found binary")
        .args(&[&temp_dir_path, "-delete", "-name", "test"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::is_empty());

    assert!(!test_file.exists(), "test file should be deleted");
    assert!(!temp_dir.path().exists(), "temp dir should also be deleted");
}

// This could be covered by a unit test in principle... in practice, changing
// the working dir can't be done safely in unit tests unless `--test-threads=1`
// or `serial` goes everywhere, and it doesn't seem possible to get an
// appropriate `walkdir::DirEntry` for "." without actually changing dirs
// (or risking deletion of the repo itself).
#[serial(working_dir)]
#[test]
fn delete_on_dot_dir() {
    let temp_dir = TempDir::new("find_cmd_").expect("made temp dir");
    let original_dir = env::current_dir().unwrap();
    env::set_current_dir(&temp_dir.path()).expect("working dir changed");

    // "." should be matched (confirmed by the print), but not deleted.
    Command::cargo_bin("find")
        .expect("found binary")
        .args(&[".", "-delete", "-print"])
        .assert()
        .success()
        .stderr(predicate::str::is_empty())
        .stdout(predicate::str::diff(".\n"));

    env::set_current_dir(original_dir).expect("restored original working dir");

    assert!(temp_dir.path().exists(), "temp dir should still exist");
}
<|endoftext|>


<commit_before>use errors;

// see OSC Type Tag String: http://opensoundcontrol.org/spec-1_0
// padding: zero bytes (n*4)

#[derive(Debug)]
pub enum OscType {
    Int(i32),
    Float(f32),
    String(String),
    Blob(Vec<u8>),
    Time(u32, u32),
    // nonstandard argument types
    // ignore them if not implemented
    Long(i64),
    Double(f64),
    Char(u8),
    Color(u32), // byte-order: RGBA
    True,
    False,
    Midi(OscMidiMessage),
    Nil,
    Inf,
    Array(Vec<OscType>),
}

#[derive(Debug)]
pub struct OscMidiMessage {
    pub port: u8,
    pub status: u8,
    pub data1: u8, // maybe use an enum for data?
    pub data2: u8,
}

/// An *osc packet* can contain an *osc message* or a bundle of nested messages
/// which is called *osc bundle*.
#[derive(Debug)]
pub enum OscPacket {
    Message(OscMessage),
    Bundle(OscBundle),
}

#[derive(Debug)]
pub struct OscMessage {
    pub addr: String,
    pub args: Option<Vec<OscType>>,
}

#[derive(Debug)]
pub struct OscBundle {
    pub timetag: OscType,
    pub content: Vec<OscPacket>,
}

pub type OscResult<T> = Result<T, errors::OscError>;
<commit_msg>Change argument type of OscChar to char<commit_after>use errors;

// see OSC Type Tag String: http://opensoundcontrol.org/spec-1_0
// padding: zero bytes (n*4)

#[derive(Debug)]
pub enum OscType {
    Int(i32),
    Float(f32),
    String(String),
    Blob(Vec<u8>),
    Time(u32, u32),
    // nonstandard argument types
    // ignore them if not implemented
    Long(i64),
    Double(f64),
    Char(char),
    Color(u32), // byte-order: RGBA
    True,
    False,
    Midi(OscMidiMessage),
    Nil,
    Inf,
    Array(Vec<OscType>),
}

#[derive(Debug)]
pub struct OscMidiMessage {
    pub port: u8,
    pub status: u8,
    pub data1: u8, // maybe use an enum for data?
    pub data2: u8,
}

/// An *osc packet* can contain an *osc message* or a bundle of nested messages
/// which is called *osc bundle*.
#[derive(Debug)]
pub enum OscPacket {
    Message(OscMessage),
    Bundle(OscBundle),
}

#[derive(Debug)]
pub struct OscMessage {
    pub addr: String,
    pub args: Option<Vec<OscType>>,
}

#[derive(Debug)]
pub struct OscBundle {
    pub timetag: OscType,
    pub content: Vec<OscPacket>,
}

pub type OscResult<T> = Result<T, errors::OscError>;
<|endoftext|>


<commit_before>#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Visibility {
    Visible,
    Invisible,
    Gone,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WindowStartSize {
    Exact(u16, u16),
    Fullscreen,
}

pub type Menu = Option<Vec<MenuItem>>;

#[derive(Debug, PartialEq)]
pub enum MenuItem {
	Action(String, crate::callbacks::Action),
	Delimiter,
	Sub(String, Vec<MenuItem>),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MessageSeverity {
    Info,
    Warning,
    Alert,
}

#[derive(Debug, Clone, PartialEq)]
pub enum TextContent {
    Plain(String),
    LabelDescription(String, String),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ImageScalePolicy {
    CropCenter, // TODO variants
    FitCenter,  // TODO variants
                // TODO Tile
}
<commit_msg>MenuItemRole<commit_after>#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Visibility {
    Visible,
    Invisible,
    Gone,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WindowStartSize {
    Exact(u16, u16),
    Fullscreen,
}

pub type Menu = Option<Vec<MenuItem>>;

#[derive(Debug, PartialEq)]
pub enum MenuItem {
	Action(String, crate::callbacks::Action, MenuItemRole),
	Delimiter,
	Sub(String, Vec<MenuItem>, MenuItemRole),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MenuItemRole {
	None,
	Options,
	Help,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MessageSeverity {
    Info,
    Warning,
    Alert,
}

#[derive(Debug, Clone, PartialEq)]
pub enum TextContent {
    Plain(String),
    LabelDescription(String, String),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ImageScalePolicy {
    CropCenter, // TODO variants
    FitCenter,  // TODO variants
                // TODO Tile
}
<|endoftext|>


<commit_before>use std::thread;
use std::sync::mpsc::channel;
use std::sync::mpsc::Sender;
use std::sync::mpsc::Receiver;

/// Create a bidirectional channel
/// Returns two sender-receiver channel pairs
/// One pair should be given to one thread
/// and the other pair to another thread
pub fn bichannel<T>() -> ((Sender<T>,Receiver<T>),(Sender<T>,Receiver<T>)){
    let side1 = channel::<T>();
    let side2 = channel::<T>();
    return ((side1.0,side2.1),(side2.0,side1.1))
}<commit_msg>Allow two way channel to have two different types<commit_after>use std::sync::mpsc::channel;
use std::sync::mpsc::Sender;
use std::sync::mpsc::Receiver;

/// Create a bidirectional channel
/// Returns two sender-receiver channel pairs
/// One pair should be given to one thread
/// and the other pair to another thread
pub fn bichannel<T, U>() -> ((Sender<T>, Receiver<U>), (Sender<U>, Receiver<T>)) {
  let side1 = channel::<T>();
  let side2 = channel::<U>();
  return ((side1.0, side2.1), (side2.0, side1.1));
}
<|endoftext|>