<commit_before>use std::char;

/// Get the unicode braille symbol for any given map of bits
///
/// # Arguments
///
/// `dotmap` - A (usually) binary literal that's used to generate the unicode
/// symbol that gets returned.
///
/// # Examples
/// make_braille(0b10011101); // Returns ⢵
pub fn make_braille(dotmap: u8) -> char {
    // Braille in unicode works weirdly so we have to warp the values
    // around.
    // See https://en.wikipedia.org/wiki/Braille_Patterns for more info
    let warped_dotmap: u8 =
        (dotmap >> 7 & 0b00000001) | // Moving 10000000 to 00000001
        (dotmap >> 3 & 0b00001000) | // Moving 01000000 to 00001000
        (dotmap >> 4 & 0b00000010) | // Moving 00100000 to 00000010
        (dotmap >> 0 & 0b00010000) | // Moving 00010000 to 00010000
        (dotmap >> 1 & 0b00000100) | // Moving 00001000 to 00000100
        (dotmap << 3 & 0b00100000) | // Moving 00000100 to 00100000
        (dotmap << 5 & 0b01000000) | // Moving 00000010 to 01000000
        (dotmap << 7 & 0b10000000);  // Moving 00000001 to 10000000
    char::from_u32(10240 + warped_dotmap as u32).unwrap()
}

#[cfg(test)]
mod tests {
    use super::make_braille;

    #[test]
    fn test_make_braille() {
        assert!(make_braille(0b00000000) == '⠀');
        assert!(make_braille(0b11111111) == '⣿');

        assert!(make_braille(0b00001111) == '⣤');
        assert!(make_braille(0b11110000) == '⠛');
        assert!(make_braille(0b10011001) == '⢕');
        assert!(make_braille(0b10101010) == '⡇');
        assert!(make_braille(0b01010101) == '⢸');

        assert!(make_braille(0b10011101) == '⢵');
    }
}
<commit_msg>Cleaned and expanded documentation in braille.rs<commit_after>use std::char;

/// Get the unicode braille symbol for any given map of bits
///
/// # Arguments
///
/// `dotmap` - A u8 that gets its bits used as a mask for which dots on the
/// braille symbol should be "lit".
///
/// # Examples
///
/// ```
/// assert!(make_braille(0b10011101) == '⢵');
/// ```
pub fn make_braille(dotmap: u8) -> char {
    // Braille in unicode works weirdly so we have to warp the bits
    // around.
    //
    // If you number each bit of a byte like 0b12345678 then a braille
    // character looks like:
    //
    //      8  5
    //      7  4
    //      6  3
    //      2  1
    //
    // This is the core reason for all the weird bitwise reordering.
    //
    // See https://en.wikipedia.org/wiki/Braille_Patterns for more info
    let warped_dotmap: u8 =
        (dotmap >> 7 & 0b00000001) | // Moving X_______ to _______X
        (dotmap >> 3 & 0b00001000) | // Moving _X______ to ____X___
        (dotmap >> 4 & 0b00000010) | // Moving __X_____ to ______X_
        (dotmap >> 0 & 0b00010000) | // Moving ___X____ to ___X____
        (dotmap >> 1 & 0b00000100) | // Moving ____X___ to _____X__
        (dotmap << 3 & 0b00100000) | // Moving _____X__ to __X_____
        (dotmap << 5 & 0b01000000) | // Moving ______X_ to _X______
        (dotmap << 7 & 0b10000000);  // Moving _______X to X_______
    char::from_u32(10240 + warped_dotmap as u32).unwrap()
}

#[cfg(test)]
mod tests {
    use super::make_braille;

    #[test]
    fn test_make_braille() {
        assert!(make_braille(0b00000000) == '⠀');
        assert!(make_braille(0b11111111) == '⣿');

        assert!(make_braille(0b00001111) == '⣤');
        assert!(make_braille(0b11110000) == '⠛');
        assert!(make_braille(0b10011001) == '⢕');
        assert!(make_braille(0b10101010) == '⡇');
        assert!(make_braille(0b01010101) == '⢸');

        assert!(make_braille(0b10011101) == '⢵');
    }
}
<|endoftext|>


<commit_before>use collections::slice::{mod, AsSlice, SlicePrelude};
use collections::vec::{mod, Vec};
use core::mem;
use core::iter::{mod, AdditiveIterator, Iterator};
use core::option::{mod, Some, None, Option};

use iobuf::Iobuf;

/// A span over potentially many Iobufs. This is useful as a "string" type where
/// the contents of the string can come from multiple IObufs, and you want to
/// avoid copying the buffer contents unnecessarily.
///
/// As an optimization, pushing an Iobuf that points to data immediately after
/// the range represented by the last Iobuf pushed will result in just expanding
/// the held Iobuf's range. This prevents allocating lots of unnecessary
/// intermediate buffers, while still maintaining the illusion of "pushing lots
/// of buffers" while incrementally parsing.
///
/// A `BufSpan` is internally represented as either an `Iobuf` or a `Vec<Iobuf>`,
/// depending on how many different buffers were used.
pub enum BufSpan<Buf> {
  Empty,
  One (Buf),
  Many(Vec<Buf>),
}

impl<Buf: Iobuf> BufSpan<Buf> {
  /// Creates a new, empty `Bufspan`.
  ///
  /// ```
  /// use iobuf::{BufSpan, ROIobuf};
  ///
  /// let s: BufSpan<ROIobuf<'static>> = BufSpan::new();
  /// assert!(s.is_empty());
  /// ```
  #[inline]
  pub fn new() -> BufSpan<Buf> {
    Empty
  }

  /// Creates a new `BufSpan` from an Iobuf.
  ///
  /// ```
  /// use iobuf::{BufSpan, Iobuf, ROIobuf};
  /// use std::iter::AdditiveIterator;
  ///
  /// let s = BufSpan::from_buf(ROIobuf::from_slice(b"hello"));
  /// assert_eq!(s.iter().count(), 1);
  /// assert_eq!(s.iter().map(|b| b.len()).sum(), 5);
  /// ```
  #[inline]
  pub fn from_buf(b: Buf) -> BufSpan<Buf> {
    One(b)
  }

  /// Returns `true` iff the span is over an empty range.
  ///
  /// ```
  /// use iobuf::{BufSpan, Iobuf, ROIobuf};
  ///
  /// let mut s = BufSpan::new();
  ///
  /// assert!(s.is_empty());
  ///
  /// s.push(ROIobuf::from_str(""));
  /// assert!(s.is_empty());
  ///
  /// s.push(ROIobuf::from_str("hello, world!"));
  /// assert!(!s.is_empty());
  /// ```
  #[inline]
  pub fn is_empty(&self) -> bool {
    match *self {
      Empty => true,
      _     => false,
    }
  }

  /// The fast path during pushing -- either fills in the first buffer, or
  /// extends an existing one.
  ///
  /// Returns `None` if the fast path was taken and nothing more needs to be
  /// done. Returns `Some` if we need to do a slow push.
  fn try_to_extend(&mut self, b: Buf) -> Option<Buf> {
    let len = b.len();
    if len == 0 { return None; }

    match *self {
      Empty => {},
      One(ref mut b0) => {
        unsafe {
          if b0.is_extended_by(&b) {
            b0.unsafe_extend(len);
            return None;
          } else {
            return Some(b); // Upgrade the `One` into a `Many` in the slow path.
          }
        }
      }
      Many(ref mut v) => {
        // I wish this wouldn't unwind, and just abort... :(
        let last = v.last_mut().unwrap();
        unsafe {
          if last.is_extended_by(&b) {
            last.unsafe_extend(len);
            return None;
          } else {
            return Some(b);
          }
        }
      }
    }

    // Handle this case in the fast path, instead of leaving it for slow_push
    // to clean up.
    *self = One(b);
    None
  }

  /// Appends a buffer to a `BufSpan`. If the buffer is an extension of the
  /// previously pushed buffer, the range will be extended. Otherwise, the new
  /// non-extension buffer will be added to the end of a vector.
  pub fn push(&mut self, b: Buf) {
    match self.try_to_extend(b) {
      None    => {},
      Some(b) => self.slow_push(b),
    }
  }

  /// The slow path during a push. This is only taken if a `BufSpan` must span
  /// multiple backing buffers.
  #[cold]
  fn slow_push(&mut self, b: Buf) {
    let this = mem::replace(self, Empty);
    *self =
      match this {
        Empty   => One(b),
        One(b0) => {
          let mut v = Vec::with_capacity(2);
          v.push(b0);
          v.push(b);
          Many(v)
        },
        Many(mut bs) => { bs.push(b); Many(bs) }
      };
  }

  /// Returns an iterator over references to the buffers inside the `BufSpan`.
  #[inline]
  pub fn iter<'a>(&'a self) -> SpanIter<'a, Buf> {
    match *self {
      Empty       => Opt(None.into_iter()),
      One (ref b) => Opt(Some(b).into_iter()),
      Many(ref v) => Lot(v.as_slice().iter()),
    }
  }

  /// Returns a moving iterator over the buffers inside the `BufSpan`.
  #[inline]
  pub fn into_iter(self) -> SpanMoveIter<Buf> {
    match self {
      Empty   => MoveOpt(None.into_iter()),
      One (b) => MoveOpt(Some(b).into_iter()),
      Many(v) => MoveLot(v.into_iter()),
    }
  }

  /// Returns an iterator over the bytes in the `BufSpan`.
  #[inline]
  pub fn iter_bytes<'a>(&'a self) -> ByteIter<'a, Buf> {
    self.iter()
        .flat_map(|buf| unsafe { buf.as_window_slice().iter() })
        .map(|&b| b)
  }

  /// Returns `true` iff the bytes in this `BufSpan` are the same as the bytes
  /// in the other `BufSpan`.
  ///
  /// ```
  /// use iobuf::{BufSpan, ROIobuf, RWIobuf};
  ///
  /// let a = BufSpan::from_buf(ROIobuf::from_str("hello"));
  /// let b = BufSpan::from_buf(RWIobuf::from_string("hello".into_string()));
  ///
  /// assert!(a.byte_equal(&b));
  ///
  /// let mut c = BufSpan::from_buf(ROIobuf::from_str("hel"));
  /// c.push(ROIobuf::from_str("lo"));
  ///
  /// assert!(a.byte_equal(&c)); assert!(c.byte_equal(&a));
  ///
  /// let d = BufSpan::from_buf(ROIobuf::from_str("helo"));
  /// assert!(!a.byte_equal(&d));
  /// ```
  #[inline]
  pub fn byte_equal<Buf2: Iobuf>(&self, other: &BufSpan<Buf2>) -> bool {
    self.count_bytes() == other.count_bytes()
    && self.iter_bytes().zip(other.iter_bytes()).all(|(a, b)| a == b)
  }

  /// A more efficient version of byte_equal, specialized to work exclusively on
  /// slices.
  ///
  /// ```
  /// use iobuf::{BufSpan, ROIobuf};
  ///
  /// let a = BufSpan::from_buf(ROIobuf::from_str("hello"));
  ///
  /// assert!(a.byte_equal_slice(b"hello"));
  /// assert!(!a.byte_equal_slice(b"helo"));
  /// ```
  #[inline]
  pub fn byte_equal_slice(&self, other: &[u8]) -> bool {
    self.count_bytes() as uint == other.len()
    && self.iter_bytes().zip(other.iter()).all(|(a, &b)| a == b)
  }

  /// Counts the number of bytes this `BufSpan` is over. This is
  /// `O(self.iter().len())`.
  #[inline]
  pub fn count_bytes(&self) -> u32 {
    // `self.iter().map(|b| b.len()).sum()` would be shorter, but I like to
    // specialize for the much more common case of empty or singular `BufSpan`s.
    match *self {
      Empty       => 0,
      One (ref b) => b.len(),
      Many(ref v) => v.iter().map(|b| b.len()).sum(),
    }
  }
}

/// An iterator over the bytes in a `BufSpan`.
pub type ByteIter<'a, Buf> =
  iter::Map<'static, &'a u8, u8,
    iter::FlatMap<'static, &'a Buf,
      SpanIter<'a, Buf>,
      slice::Items<'a, u8>>>;

/// An iterator over references to buffers inside a `BufSpan`.
pub enum SpanIter<'a, Buf: 'a> {
  Opt(option::Item<&'a Buf>),
  Lot(slice::Items<'a, Buf>),
}

impl<'a, Buf: Iobuf> Iterator<&'a Buf> for SpanIter<'a, Buf> {
  #[inline(always)]
  fn next(&mut self) -> Option<&'a Buf> {
    // I'm couting on this match getting lifted out of the loop with
    // loop-invariant code motion.
    match *self {
      Opt(ref mut iter) => iter.next(),
      Lot(ref mut iter) => iter.next(),
    }
  }

  #[inline(always)]
  fn size_hint(&self) -> (uint, Option<uint>) {
    match *self {
      Opt(ref iter) => iter.size_hint(),
      Lot(ref iter) => iter.size_hint(),
    }
  }
}

/// A moving iterator over buffers inside a `BufSpan`.
pub enum SpanMoveIter<Buf> {
  MoveOpt(option::Item<Buf>),
  MoveLot(vec::MoveItems<Buf>),
}

impl<Buf: Iobuf> Iterator<Buf> for SpanMoveIter<Buf> {
  #[inline(always)]
  fn next(&mut self) -> Option<Buf> {
    // I'm couting on this match getting lifted out of the loop with
    // loop-invariant code motion.
    match *self {
      MoveOpt(ref mut iter) => iter.next(),
      MoveLot(ref mut iter) => iter.next(),
    }
  }

  #[inline(always)]
  fn size_hint(&self) -> (uint, Option<uint>) {
    match *self {
      MoveOpt(ref iter) => iter.size_hint(),
      MoveLot(ref iter) => iter.size_hint(),
    }
  }
}
<commit_msg>use .count_bytes in the docs<commit_after>use collections::slice::{mod, AsSlice, SlicePrelude};
use collections::vec::{mod, Vec};
use core::mem;
use core::iter::{mod, AdditiveIterator, Iterator};
use core::option::{mod, Some, None, Option};

use iobuf::Iobuf;

/// A span over potentially many Iobufs. This is useful as a "string" type where
/// the contents of the string can come from multiple IObufs, and you want to
/// avoid copying the buffer contents unnecessarily.
///
/// As an optimization, pushing an Iobuf that points to data immediately after
/// the range represented by the last Iobuf pushed will result in just expanding
/// the held Iobuf's range. This prevents allocating lots of unnecessary
/// intermediate buffers, while still maintaining the illusion of "pushing lots
/// of buffers" while incrementally parsing.
///
/// A `BufSpan` is internally represented as either an `Iobuf` or a `Vec<Iobuf>`,
/// depending on how many different buffers were used.
pub enum BufSpan<Buf> {
  Empty,
  One (Buf),
  Many(Vec<Buf>),
}

impl<Buf: Iobuf> BufSpan<Buf> {
  /// Creates a new, empty `Bufspan`.
  ///
  /// ```
  /// use iobuf::{BufSpan, ROIobuf};
  ///
  /// let s: BufSpan<ROIobuf<'static>> = BufSpan::new();
  /// assert!(s.is_empty());
  /// ```
  #[inline]
  pub fn new() -> BufSpan<Buf> {
    Empty
  }

  /// Creates a new `BufSpan` from an Iobuf.
  ///
  /// ```
  /// use iobuf::{BufSpan, ROIobuf};
  ///
  /// let s = BufSpan::from_buf(ROIobuf::from_slice(b"hello"));
  /// assert_eq!(s.iter().count(), 1);
  /// assert_eq!(s.count_bytes(), 5);
  /// ```
  #[inline]
  pub fn from_buf(b: Buf) -> BufSpan<Buf> {
    One(b)
  }

  /// Returns `true` iff the span is over an empty range.
  ///
  /// ```
  /// use iobuf::{BufSpan, Iobuf, ROIobuf};
  ///
  /// let mut s = BufSpan::new();
  ///
  /// assert!(s.is_empty());
  ///
  /// s.push(ROIobuf::from_str(""));
  /// assert!(s.is_empty());
  ///
  /// s.push(ROIobuf::from_str("hello, world!"));
  /// assert!(!s.is_empty());
  /// ```
  #[inline]
  pub fn is_empty(&self) -> bool {
    match *self {
      Empty => true,
      _     => false,
    }
  }

  /// The fast path during pushing -- either fills in the first buffer, or
  /// extends an existing one.
  ///
  /// Returns `None` if the fast path was taken and nothing more needs to be
  /// done. Returns `Some` if we need to do a slow push.
  fn try_to_extend(&mut self, b: Buf) -> Option<Buf> {
    let len = b.len();
    if len == 0 { return None; }

    match *self {
      Empty => {},
      One(ref mut b0) => {
        unsafe {
          if b0.is_extended_by(&b) {
            b0.unsafe_extend(len);
            return None;
          } else {
            return Some(b); // Upgrade the `One` into a `Many` in the slow path.
          }
        }
      }
      Many(ref mut v) => {
        // I wish this wouldn't unwind, and just abort... :(
        let last = v.last_mut().unwrap();
        unsafe {
          if last.is_extended_by(&b) {
            last.unsafe_extend(len);
            return None;
          } else {
            return Some(b);
          }
        }
      }
    }

    // Handle this case in the fast path, instead of leaving it for slow_push
    // to clean up.
    *self = One(b);
    None
  }

  /// Appends a buffer to a `BufSpan`. If the buffer is an extension of the
  /// previously pushed buffer, the range will be extended. Otherwise, the new
  /// non-extension buffer will be added to the end of a vector.
  pub fn push(&mut self, b: Buf) {
    match self.try_to_extend(b) {
      None    => {},
      Some(b) => self.slow_push(b),
    }
  }

  /// The slow path during a push. This is only taken if a `BufSpan` must span
  /// multiple backing buffers.
  #[cold]
  fn slow_push(&mut self, b: Buf) {
    let this = mem::replace(self, Empty);
    *self =
      match this {
        Empty   => One(b),
        One(b0) => {
          let mut v = Vec::with_capacity(2);
          v.push(b0);
          v.push(b);
          Many(v)
        },
        Many(mut bs) => { bs.push(b); Many(bs) }
      };
  }

  /// Returns an iterator over references to the buffers inside the `BufSpan`.
  #[inline]
  pub fn iter<'a>(&'a self) -> SpanIter<'a, Buf> {
    match *self {
      Empty       => Opt(None.into_iter()),
      One (ref b) => Opt(Some(b).into_iter()),
      Many(ref v) => Lot(v.as_slice().iter()),
    }
  }

  /// Returns a moving iterator over the buffers inside the `BufSpan`.
  #[inline]
  pub fn into_iter(self) -> SpanMoveIter<Buf> {
    match self {
      Empty   => MoveOpt(None.into_iter()),
      One (b) => MoveOpt(Some(b).into_iter()),
      Many(v) => MoveLot(v.into_iter()),
    }
  }

  /// Returns an iterator over the bytes in the `BufSpan`.
  #[inline]
  pub fn iter_bytes<'a>(&'a self) -> ByteIter<'a, Buf> {
    self.iter()
        .flat_map(|buf| unsafe { buf.as_window_slice().iter() })
        .map(|&b| b)
  }

  /// Returns `true` iff the bytes in this `BufSpan` are the same as the bytes
  /// in the other `BufSpan`.
  ///
  /// ```
  /// use iobuf::{BufSpan, ROIobuf, RWIobuf};
  ///
  /// let a = BufSpan::from_buf(ROIobuf::from_str("hello"));
  /// let b = BufSpan::from_buf(RWIobuf::from_string("hello".into_string()));
  ///
  /// assert!(a.byte_equal(&b));
  ///
  /// let mut c = BufSpan::from_buf(ROIobuf::from_str("hel"));
  /// c.push(ROIobuf::from_str("lo"));
  ///
  /// assert!(a.byte_equal(&c)); assert!(c.byte_equal(&a));
  ///
  /// let d = BufSpan::from_buf(ROIobuf::from_str("helo"));
  /// assert!(!a.byte_equal(&d));
  /// ```
  #[inline]
  pub fn byte_equal<Buf2: Iobuf>(&self, other: &BufSpan<Buf2>) -> bool {
    self.count_bytes() == other.count_bytes()
    && self.iter_bytes().zip(other.iter_bytes()).all(|(a, b)| a == b)
  }

  /// A more efficient version of byte_equal, specialized to work exclusively on
  /// slices.
  ///
  /// ```
  /// use iobuf::{BufSpan, ROIobuf};
  ///
  /// let a = BufSpan::from_buf(ROIobuf::from_str("hello"));
  ///
  /// assert!(a.byte_equal_slice(b"hello"));
  /// assert!(!a.byte_equal_slice(b"helo"));
  /// ```
  #[inline]
  pub fn byte_equal_slice(&self, other: &[u8]) -> bool {
    self.count_bytes() as uint == other.len()
    && self.iter_bytes().zip(other.iter()).all(|(a, &b)| a == b)
  }

  /// Counts the number of bytes this `BufSpan` is over. This is
  /// `O(self.iter().len())`.
  #[inline]
  pub fn count_bytes(&self) -> u32 {
    // `self.iter().map(|b| b.len()).sum()` would be shorter, but I like to
    // specialize for the much more common case of empty or singular `BufSpan`s.
    match *self {
      Empty       => 0,
      One (ref b) => b.len(),
      Many(ref v) => v.iter().map(|b| b.len()).sum(),
    }
  }
}

/// An iterator over the bytes in a `BufSpan`.
pub type ByteIter<'a, Buf> =
  iter::Map<'static, &'a u8, u8,
    iter::FlatMap<'static, &'a Buf,
      SpanIter<'a, Buf>,
      slice::Items<'a, u8>>>;

/// An iterator over references to buffers inside a `BufSpan`.
pub enum SpanIter<'a, Buf: 'a> {
  Opt(option::Item<&'a Buf>),
  Lot(slice::Items<'a, Buf>),
}

impl<'a, Buf: Iobuf> Iterator<&'a Buf> for SpanIter<'a, Buf> {
  #[inline(always)]
  fn next(&mut self) -> Option<&'a Buf> {
    // I'm couting on this match getting lifted out of the loop with
    // loop-invariant code motion.
    match *self {
      Opt(ref mut iter) => iter.next(),
      Lot(ref mut iter) => iter.next(),
    }
  }

  #[inline(always)]
  fn size_hint(&self) -> (uint, Option<uint>) {
    match *self {
      Opt(ref iter) => iter.size_hint(),
      Lot(ref iter) => iter.size_hint(),
    }
  }
}

/// A moving iterator over buffers inside a `BufSpan`.
pub enum SpanMoveIter<Buf> {
  MoveOpt(option::Item<Buf>),
  MoveLot(vec::MoveItems<Buf>),
}

impl<Buf: Iobuf> Iterator<Buf> for SpanMoveIter<Buf> {
  #[inline(always)]
  fn next(&mut self) -> Option<Buf> {
    // I'm couting on this match getting lifted out of the loop with
    // loop-invariant code motion.
    match *self {
      MoveOpt(ref mut iter) => iter.next(),
      MoveLot(ref mut iter) => iter.next(),
    }
  }

  #[inline(always)]
  fn size_hint(&self) -> (uint, Option<uint>) {
    match *self {
      MoveOpt(ref iter) => iter.size_hint(),
      MoveLot(ref iter) => iter.size_hint(),
    }
  }
}
<|endoftext|>


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

use super::*;

pub struct Builder {
    pub ptr: LLVMBuilderRef
}
impl_llvm_ref!(Builder, LLVMBuilderRef);

impl Builder {
    pub fn position_at_end(&mut self, basic_block: LLVMBasicBlockRef) {
        unsafe {
            llvm::LLVMPositionBuilderAtEnd(self.ptr, basic_block);
        }
    }

    pub fn build_ret(&mut self, ret_val: LLVMValueRef) -> LLVMValueRef {
        unsafe {
            llvm::LLVMBuildRet(self.ptr, ret_val)
        }
    }

    pub fn build_ret_void(&self) -> LLVMValueRef {
        unsafe {
            llvm::LLVMBuildRetVoid(self.ptr)
        }
    }

    pub fn build_alloca(&mut self, ty: LLVMTypeRef, name: &str) -> LLVMValueRef {
        let c_name = CString::new(name).unwrap();
        unsafe {
            llvm::LLVMBuildAlloca(self.ptr, ty, c_name.as_ptr())
        }
    }

    pub fn build_store(&mut self, val: LLVMValueRef, ptr: LLVMValueRef) -> LLVMValueRef {
        unsafe {
            llvm::LLVMBuildStore(self.ptr, val, ptr)
        }
    }

    pub fn build_load(&mut self, ptr: LLVMValueRef, name: &str) -> LLVMValueRef {
        let c_name = CString::new(name).unwrap();
        unsafe {
            llvm::LLVMBuildLoad(self.ptr, ptr, c_name.as_ptr())
        }
    }

    pub fn build_call(&mut self, func: Function, mut args: Vec<LLVMValueRef>,
                      name: &str) -> LLVMValueRef {
        let c_name = CString::new(name).unwrap();
        unsafe {
            llvm::LLVMBuildCall(
                self.ptr,
                func.ptr,
                args.as_mut_ptr(),
                args.len() as u32,
                c_name.as_ptr()
            )
        }
    }

    pub fn build_add(&mut self, lhs: LLVMValueRef, rhs: LLVMValueRef, name: &str) -> LLVMValueRef {
        let c_name = CString::new(name).unwrap();
        unsafe {
            llvm::LLVMBuildAdd(self.ptr, lhs, rhs, c_name.as_ptr())
        }
    }

    pub fn build_sub(&mut self, lhs: LLVMValueRef, rhs: LLVMValueRef, name: &str) -> LLVMValueRef {
        let c_name = CString::new(name).unwrap();
        unsafe {
            llvm::LLVMBuildSub(self.ptr, lhs, rhs, c_name.as_ptr())
        }
    }

    pub fn build_mul(&mut self, lhs: LLVMValueRef, rhs: LLVMValueRef, name: &str) -> LLVMValueRef {
        let c_name = CString::new(name).unwrap();
        unsafe {
            llvm::LLVMBuildMul(self.ptr, lhs, rhs, c_name.as_ptr())
        }
    }

    pub fn build_sdiv(&mut self, lhs: LLVMValueRef, rhs: LLVMValueRef,
                      name: &str) -> LLVMValueRef {
        let c_name = CString::new(name).unwrap();
        unsafe {
            llvm::LLVMBuildSDiv(self.ptr, lhs, rhs, c_name.as_ptr())
        }
    }

    pub fn build_icmp(&mut self, op: LLVMIntPredicate, lhs: LLVMValueRef, rhs: LLVMValueRef,
                      name: &str) -> LLVMValueRef {
        let c_name = CString::new(name).unwrap();
        unsafe {
            llvm::LLVMBuildICmp(self.ptr, op, lhs, rhs, c_name.as_ptr())
        }
    }

    pub fn build_global_string(&self, s: &str, name: &str) -> LLVMValueRef {
        let c_s = CString::new(s).unwrap();
        let c_name = CString::new(name).unwrap();
        unsafe {
            llvm::LLVMBuildGlobalString(self.ptr, c_s.as_ptr(), c_name.as_ptr())
        }
    }

    pub fn build_in_bounds_gep(&self, ptr: LLVMValueRef, mut indices: Vec<LLVMValueRef>,
                               name: &str) -> LLVMValueRef {
        let c_name = CString::new(name).unwrap();
        unsafe {
            llvm::LLVMBuildInBoundsGEP(self.ptr, ptr, indices.as_mut_ptr(),
                                       indices.len() as u32, c_name.as_ptr())
        }
    }

    pub fn build_cond_br(&self, cond: LLVMValueRef, then: LLVMBasicBlockRef,
                         else_: LLVMBasicBlockRef) -> LLVMValueRef {
        unsafe {
            llvm::LLVMBuildCondBr(self.ptr, cond, then, else_)
        }
    }

    pub fn build_br(&self, dest: LLVMBasicBlockRef) -> LLVMValueRef {
        unsafe {
            llvm::LLVMBuildBr(self.ptr, dest)
        }
    }

}

impl Drop for Builder {
    fn drop(&mut self) {
        unsafe {
            llvm::LLVMDisposeBuilder(self.ptr);
        }
    }
}

<commit_msg>Add more builder ops (#7)<commit_after>use llvm_sys::*;
use llvm_sys::prelude::*;
use llvm_sys::core as llvm;

use super::*;

macro_rules! build_op_str {
    ($op_name: ident, $fn: path, $($argn: ident: $argv: path),*) => {
        impl Builder {
            pub fn $op_name(&mut self, $($argn: $argv),*, name: &str) -> LLVMValueRef {
                let c_name = CString::new(name).unwrap();
                unsafe {
                    $fn(self.ptr, $($argn),*, c_name.as_ptr())
                }
            }
        }
    }
}

macro_rules! build_op {
    ($op_name: ident, $fn: path, $($argn: ident: $argv: path),*) => {
        impl Builder {
            pub fn $op_name(&mut self, $($argn: $argv),*) -> LLVMValueRef {
                unsafe {
                    $fn(self.ptr, $($argn),*)
                }
            }
        }
    }
}

pub struct Builder {
    pub ptr: LLVMBuilderRef
}
impl_llvm_ref!(Builder, LLVMBuilderRef);

// http://llvm.org/docs/doxygen/html/group__LLVMCCoreInstructionBuilder.html
//TODO: Get/Set Volatile
//TODO: Get/Set Ordering
//TODO: Almost everything from LLVMBuildAdd and upwards

build_op_str!(build_add, llvm::LLVMBuildAdd, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_sub, llvm::LLVMBuildSub, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_mul, llvm::LLVMBuildMul, lhs: LLVMValueRef, rhs: LLVMValueRef);

build_op_str!(build_fadd, llvm::LLVMBuildFAdd, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_fsub, llvm::LLVMBuildFSub, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_fmul, llvm::LLVMBuildFMul, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_fdiv, llvm::LLVMBuildFDiv, lhs: LLVMValueRef, rhs: LLVMValueRef);

build_op_str!(build_nswadd, llvm::LLVMBuildNSWAdd, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_nswsub, llvm::LLVMBuildNSWSub, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_nswmul, llvm::LLVMBuildNSWMul, lhs: LLVMValueRef, rhs: LLVMValueRef);

build_op_str!(build_nuwadd, llvm::LLVMBuildNUWAdd, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_nuwsub, llvm::LLVMBuildNUWSub, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_nuwmul, llvm::LLVMBuildNUWMul, lhs: LLVMValueRef, rhs: LLVMValueRef);

build_op_str!(build_udiv, llvm::LLVMBuildUDiv, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_sdiv, llvm::LLVMBuildSDiv, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_exact_sdiv, llvm::LLVMBuildExactSDiv, lhs: LLVMValueRef, rhs: LLVMValueRef);

build_op_str!(build_urem, llvm::LLVMBuildURem, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_srem, llvm::LLVMBuildSRem, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_frem, llvm::LLVMBuildFRem, lhs: LLVMValueRef, rhs: LLVMValueRef);

build_op_str!(build_shl, llvm::LLVMBuildShl, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_lshr, llvm::LLVMBuildLShr, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_ashr, llvm::LLVMBuildAShr, lhs: LLVMValueRef, rhs: LLVMValueRef);

build_op_str!(build_and, llvm::LLVMBuildAnd, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_or, llvm::LLVMBuildOr, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_xor, llvm::LLVMBuildXor, lhs: LLVMValueRef, rhs: LLVMValueRef);

// TODO: LLVMBuildBinOp

build_op_str!(build_neg, llvm::LLVMBuildNeg, v: LLVMValueRef);
build_op_str!(build_fneg, llvm::LLVMBuildFNeg, v: LLVMValueRef);
build_op_str!(build_nswneg, llvm::LLVMBuildNSWNeg, v: LLVMValueRef);
build_op_str!(build_nuwneg, llvm::LLVMBuildNUWNeg, v: LLVMValueRef);

build_op_str!(build_not, llvm::LLVMBuildNot, v: LLVMValueRef);

build_op_str!(build_malloc, llvm::LLVMBuildMalloc, typ: LLVMTypeRef);
build_op_str!(build_array_malloc, llvm::LLVMBuildArrayMalloc, typ: LLVMTypeRef,
                                                              val: LLVMValueRef);

build_op_str!(build_alloca, llvm::LLVMBuildAlloca, ty: LLVMTypeRef);
build_op_str!(build_array_alloca, llvm::LLVMBuildArrayAlloca, ty: LLVMTypeRef,
                                                              val: LLVMValueRef);

build_op!(build_free, llvm::LLVMBuildFree, pval: LLVMValueRef);
build_op_str!(build_load, llvm::LLVMBuildLoad, ptr: LLVMValueRef);
build_op!(build_store, llvm::LLVMBuildStore,  val: LLVMValueRef, pval: LLVMValueRef);

build_op_str!(build_trunc, llvm::LLVMBuildTrunc, val: LLVMValueRef, dest_ty: LLVMTypeRef);
build_op_str!(build_zext, llvm::LLVMBuildZExt, val: LLVMValueRef, dest_ty: LLVMTypeRef);
build_op_str!(build_sext, llvm::LLVMBuildSExt, val: LLVMValueRef, dest_ty: LLVMTypeRef);
build_op_str!(build_fp_to_ui, llvm::LLVMBuildFPToUI, val: LLVMValueRef, dest_ty: LLVMTypeRef);
build_op_str!(build_fp_to_si, llvm::LLVMBuildFPToSI, val: LLVMValueRef, dest_ty: LLVMTypeRef);
build_op_str!(build_ui_to_fp, llvm::LLVMBuildUIToFP, val: LLVMValueRef, dest_ty: LLVMTypeRef);
build_op_str!(build_si_to_fp, llvm::LLVMBuildSIToFP, val: LLVMValueRef, dest_ty: LLVMTypeRef);
build_op_str!(build_fp_trunc, llvm::LLVMBuildFPTrunc, val: LLVMValueRef, dest_ty: LLVMTypeRef);
build_op_str!(build_fp_ext, llvm::LLVMBuildFPExt, val: LLVMValueRef, dest_ty: LLVMTypeRef);
build_op_str!(build_ptr_to_int, llvm::LLVMBuildPtrToInt, val: LLVMValueRef, dest_ty: LLVMTypeRef);
build_op_str!(build_int_to_ptr, llvm::LLVMBuildIntToPtr, val: LLVMValueRef, dest_ty: LLVMTypeRef);

build_op_str!(build_bit_cast, llvm::LLVMBuildBitCast, val: LLVMValueRef, dest_ty: LLVMTypeRef);
build_op_str!(build_addr_space_cast, llvm::LLVMBuildAddrSpaceCast, val: LLVMValueRef,
                                                                   dest_ty: LLVMTypeRef);
build_op_str!(build_zext_or_bit_cast, llvm::LLVMBuildZExtOrBitCast, val: LLVMValueRef,
                                                                    dest_ty: LLVMTypeRef);
build_op_str!(build_sext_or_bit_cast, llvm::LLVMBuildSExtOrBitCast, val: LLVMValueRef,
                                                                    dest_ty: LLVMTypeRef);
build_op_str!(build_trunc_or_bit_cast, llvm::LLVMBuildTruncOrBitCast, val: LLVMValueRef,
                                                                      dest_ty: LLVMTypeRef);

// TODO: improve LLVMOpcode
build_op_str!(build_cast, llvm::LLVMBuildCast, op: LLVMOpcode,
                                               val: LLVMValueRef,
                                               dest_ty: LLVMTypeRef);

build_op_str!(build_pointer_cast, llvm::LLVMBuildPointerCast, val: LLVMValueRef, dest_ty: LLVMTypeRef);
build_op_str!(build_int_cast, llvm::LLVMBuildIntCast, val: LLVMValueRef, dest_ty: LLVMTypeRef);
build_op_str!(build_fpcast, llvm::LLVMBuildFPCast, val: LLVMValueRef, dest_ty: LLVMTypeRef);

build_op_str!(build_icmp, llvm::LLVMBuildICmp, op: LLVMIntPredicate,
                                               lhs: LLVMValueRef,
                                               rhs: LLVMValueRef);

build_op_str!(build_fcmp, llvm::LLVMBuildFCmp, op: LLVMRealPredicate,
                                               lhs: LLVMValueRef,
                                               rhs: LLVMValueRef);

build_op_str!(build_phi, llvm::LLVMBuildPhi, ty: LLVMTypeRef);
//build_call is manually defined in impl Builder
build_op_str!(build_select, llvm::LLVMBuildSelect, i: LLVMValueRef,
                                                   the: LLVMValueRef,
                                                   els: LLVMValueRef);

build_op_str!(build_vaarg, llvm::LLVMBuildVAArg, list: LLVMValueRef, ty: LLVMTypeRef);

build_op_str!(build_extract_element, llvm::LLVMBuildExtractElement, vec_val: LLVMValueRef,
                                                                    index: LLVMValueRef);
build_op_str!(build_insert_element, llvm::LLVMBuildInsertElement, vec_val: LLVMValueRef,
                                                                  eltval: LLVMValueRef,
                                                                  index: LLVMValueRef);
build_op_str!(build_shuffle_vector, llvm::LLVMBuildShuffleVector, v1: LLVMValueRef,
                                                                  v2: LLVMValueRef,
                                                                  mask: LLVMValueRef);

// TODO: Both these types use unsigned, change this to libc::unsigned
build_op_str!(build_extract_value, llvm::LLVMBuildExtractValue, aggval: LLVMValueRef,
                                                                index: u32);
build_op_str!(build_insert_value, llvm::LLVMBuildInsertValue, aggval: LLVMValueRef,
                                                              eltval: LLVMValueRef,
                                                              index: u32);

// TODO: LLVMBuildAtomicRMW

build_op_str!(build_is_null, llvm::LLVMBuildIsNull, val: LLVMValueRef);
build_op_str!(build_is_not_null, llvm::LLVMBuildIsNotNull, val: LLVMValueRef);
build_op_str!(build_ptr_diff, llvm::LLVMBuildPtrDiff, lhs: LLVMValueRef, rhs: LLVMValueRef);
build_op_str!(build_fence, llvm::LLVMBuildFence, ordering: LLVMAtomicOrdering,
                                                 singlethread: LLVMBool);

build_op!(build_ret, llvm::LLVMBuildRet, ret_val: LLVMValueRef);
build_op!(build_ret_void, llvm::LLVMBuildRetVoid,); // TODO: Fix the trailing comma
build_op!(build_br, llvm::LLVMBuildBr, dest: LLVMBasicBlockRef);

build_op!(build_cond_br, llvm::LLVMBuildCondBr, cond: LLVMValueRef,
                                                then: LLVMBasicBlockRef,
                                                else_: LLVMBasicBlockRef);

impl Builder {
    pub fn position_at_end(&mut self, basic_block: LLVMBasicBlockRef) {
        unsafe {
            llvm::LLVMPositionBuilderAtEnd(self.ptr, basic_block);
        }
    }

    pub fn build_call(&mut self, func: Function, mut args: Vec<LLVMValueRef>,
                      name: &str) -> LLVMValueRef {
        let c_name = CString::new(name).unwrap();
        unsafe {
            llvm::LLVMBuildCall(
                self.ptr,
                func.ptr,
                args.as_mut_ptr(),
                args.len() as u32,
                c_name.as_ptr()
            )
        }
    }
    pub fn build_global_string(&self, s: &str, name: &str) -> LLVMValueRef {
        let c_s = CString::new(s).unwrap();
        let c_name = CString::new(name).unwrap();
        unsafe {
            llvm::LLVMBuildGlobalString(self.ptr, c_s.as_ptr(), c_name.as_ptr())
        }
    }

    pub fn build_global_string_ptr(&self, s: &str, name: &str) -> LLVMValueRef {
        let c_s = CString::new(s).unwrap();
        let c_name = CString::new(name).unwrap();
        unsafe {
            llvm::LLVMBuildGlobalStringPtr(self.ptr, c_s.as_ptr(), c_name.as_ptr())
        }
    }

    pub fn build_in_bounds_gep(&self, ptr: LLVMValueRef, mut indices: Vec<LLVMValueRef>,
                               name: &str) -> LLVMValueRef {
        let c_name = CString::new(name).unwrap();
        unsafe {
            llvm::LLVMBuildInBoundsGEP(self.ptr, ptr, indices.as_mut_ptr(),
                                       indices.len() as u32, c_name.as_ptr())
        }
    }
    pub fn build_gep(&self, ptr: LLVMValueRef, mut indices: Vec<LLVMValueRef>,
                               name: &str) -> LLVMValueRef {
        let c_name = CString::new(name).unwrap();
        unsafe {
            llvm::LLVMBuildGEP(self.ptr, ptr, indices.as_mut_ptr(),
                                       indices.len() as u32, c_name.as_ptr())
        }
    }
}

impl Drop for Builder {
    fn drop(&mut self) {
        unsafe {
            llvm::LLVMDisposeBuilder(self.ptr);
        }
    }
}

<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::sync::mpsc::Sender;

use message::Message;

pub type ChatMap = HashMap<String, ClientInfo>;

pub struct ClientInfo {
    pub partner: Option<String>,
    pub sender_to_client: Sender<Message>,
    pub blocked_users : Vec<String>
}

pub fn is_valid_username(chat_map: &ChatMap, username: String) -> bool {
	username.len() > 0  && &username[0..1] != "/" && !chat_map.contains_key(&username)
}

pub fn available_users(chat_map: &ChatMap, username: String) -> Vec<String> {
	let mut v = Vec::new();
    let my_client_info = chat_map.get(&username).unwrap();
    let my_blocked_users = &my_client_info.blocked_users;

	for (name, client_info) in chat_map.iter() {
        if &name[..] != &username[..]
          && client_info.partner == None
          && !client_info.blocked_users.contains(&username)
          && !my_blocked_users.contains(name) {
            v.push(name.to_string());
        }
    }
    v
}

pub fn quit_conversation(chat_map: &mut ChatMap, username: String) {
    chat_map.get_mut(&username).unwrap().partner = None;
}

#[cfg(test)]
mod chatmap_tests {

    use std::sync::mpsc::channel;
    use super::{ChatMap, ClientInfo};
    use super::is_valid_username;

	#[test]
    fn is_valid_username_test_valid() {
    	let cm = fixture();
    	assert!(is_valid_username(&cm, "f".to_string()));
    	assert!(is_valid_username(&cm, "g".to_string()));
    	assert!(is_valid_username(&cm, "7".to_string()));
    	assert!(is_valid_username(&cm, ".".to_string()));
    	assert!(is_valid_username(&cm, "hello".to_string()));
    }

    #[test]
	fn is_valid_username_test_invalid() {
    	let cm = fixture();
    	assert!(!is_valid_username(&cm, "e".to_string()));
    	assert!(!is_valid_username(&cm, "".to_string()));
    	assert!(!is_valid_username(&cm, "/f".to_string()));
    	assert!(!is_valid_username(&cm, "/hello".to_string()));
    }

    use super::available_users;

    #[test]
    fn available_users_test_1() {
    	let cm = fixture();
    	let avail = available_users(&cm, "a".to_string());
    	assert!(avail.contains(&"b".to_string()));
    	assert!(avail.contains(&"c".to_string()));
    	assert!(avail.contains(&"d".to_string()));
    	assert!(avail.contains(&"e".to_string()));
    }

    #[test]
    fn available_users_test_2() {
    	let mut cm = fixture();

    	// Set c and d as partners
    	cm.get_mut(&"c".to_string()).unwrap().partner = Some("d".to_string());
    	cm.get_mut(&"d".to_string()).unwrap().partner = Some("c".to_string());

    	let avail = available_users(&cm, "a".to_string());
    	assert!(avail.contains(&"b".to_string()));
    	assert!(!avail.contains(&"c".to_string()));
    	assert!(!avail.contains(&"d".to_string()));
    	assert!(avail.contains(&"e".to_string()));
    }

    use super::quit_conversation;

    #[test]
    fn quit_conversation_test_1() {
        let mut cm = fixture();

        // Set a and b as partners
        cm.get_mut(&"a".to_string()).unwrap().partner = Some("b".to_string());
        cm.get_mut(&"b".to_string()).unwrap().partner = Some("a".to_string());

        quit_conversation(&mut cm, "a".to_string());

        assert_eq!(None, cm.get(&"a".to_string()).unwrap().partner);
        assert_eq!(Some("a".to_string()), cm.get(&"b".to_string()).unwrap().partner);
    }

    #[test]
    fn quit_conversation_test_2() {
        let mut cm = fixture();

        // Set a and b as partners
        cm.get_mut(&"a".to_string()).unwrap().partner = Some("b".to_string());
        cm.get_mut(&"b".to_string()).unwrap().partner = Some("a".to_string());

        // Set c and d as partners
        cm.get_mut(&"c".to_string()).unwrap().partner = Some("d".to_string());
        cm.get_mut(&"d".to_string()).unwrap().partner = Some("c".to_string());

        quit_conversation(&mut cm, "a".to_string());
        quit_conversation(&mut cm, "b".to_string());

        assert_eq!(None, cm.get(&"a".to_string()).unwrap().partner);
        assert_eq!(None, cm.get(&"b".to_string()).unwrap().partner);
        assert_eq!(Some("d".to_string()), cm.get(&"c".to_string()).unwrap().partner);
        assert_eq!(Some("c".to_string()), cm.get(&"d".to_string()).unwrap().partner);
    }

    #[test]
    fn quit_conversation_test_3() {
        let mut cm = fixture();

        // Set a and b as partners
        cm.get_mut(&"a".to_string()).unwrap().partner = Some("b".to_string());
        cm.get_mut(&"b".to_string()).unwrap().partner = Some("a".to_string());

        quit_conversation(&mut cm, "a".to_string());

        // Set a and c as partners
        cm.get_mut(&"a".to_string()).unwrap().partner = Some("c".to_string());
        cm.get_mut(&"c".to_string()).unwrap().partner = Some("a".to_string());

        quit_conversation(&mut cm, "b".to_string());

        assert_eq!(Some("c".to_string()), cm.get(&"a".to_string()).unwrap().partner);
        assert_eq!(None, cm.get(&"b".to_string()).unwrap().partner);
        assert_eq!(Some("a".to_string()), cm.get(&"c".to_string()).unwrap().partner);
    }

	fn fixture() -> ChatMap {
        let mut cm = ChatMap::new();
        let (sender_to_a, _) = channel();
        cm.insert("a".to_string(), ClientInfo{
            partner: None,
            sender_to_client: sender_to_a,
            blocked_users: Vec::new()
        });
        let (sender_to_b, _) = channel();
        cm.insert("b".to_string(), ClientInfo{
            partner: None,
            sender_to_client: sender_to_b,
            blocked_users: Vec::new()
        });
        let (sender_to_c, _) = channel();
        cm.insert("c".to_string(), ClientInfo{
            partner: None,
            sender_to_client: sender_to_c,
            blocked_users: Vec::new()
        });
        let (sender_to_d, _) = channel();
        cm.insert("d".to_string(), ClientInfo{
            partner: None,
            sender_to_client: sender_to_d,
            blocked_users: Vec::new()
        });
        let (sender_to_e, _) = channel();
        cm.insert("e".to_string(), ClientInfo{
            partner: None,
            sender_to_client: sender_to_e,
            blocked_users: Vec::new()
        });
        cm
    }
}<commit_msg>Tests for available_users with blocking<commit_after>use std::collections::HashMap;
use std::sync::mpsc::Sender;

use message::Message;

pub type ChatMap = HashMap<String, ClientInfo>;

pub struct ClientInfo {
    pub partner: Option<String>,
    pub sender_to_client: Sender<Message>,
    pub blocked_users : Vec<String>
}

pub fn is_valid_username(chat_map: &ChatMap, username: String) -> bool {
	username.len() > 0  && &username[0..1] != "/" && !chat_map.contains_key(&username)
}

pub fn available_users(chat_map: &ChatMap, username: String) -> Vec<String> {
	let mut v = Vec::new();
    let my_client_info = chat_map.get(&username).unwrap();
    let my_blocked_users = &my_client_info.blocked_users;

	for (name, client_info) in chat_map.iter() {
        if &name[..] != &username[..]
          && client_info.partner == None
          && !client_info.blocked_users.contains(&username)
          && !my_blocked_users.contains(name) {
            v.push(name.to_string());
        }
    }
    v
}

pub fn quit_conversation(chat_map: &mut ChatMap, username: String) {
    chat_map.get_mut(&username).unwrap().partner = None;
}

#[cfg(test)]
mod chatmap_tests {

    use std::sync::mpsc::channel;
    use super::{ChatMap, ClientInfo};
    use super::is_valid_username;

	#[test]
    fn is_valid_username_test_valid() {
    	let cm = fixture();
    	assert!(is_valid_username(&cm, "f".to_string()));
    	assert!(is_valid_username(&cm, "g".to_string()));
    	assert!(is_valid_username(&cm, "7".to_string()));
    	assert!(is_valid_username(&cm, ".".to_string()));
    	assert!(is_valid_username(&cm, "hello".to_string()));
    }

    #[test]
	fn is_valid_username_test_invalid() {
    	let cm = fixture();
    	assert!(!is_valid_username(&cm, "e".to_string()));
    	assert!(!is_valid_username(&cm, "".to_string()));
    	assert!(!is_valid_username(&cm, "/f".to_string()));
    	assert!(!is_valid_username(&cm, "/hello".to_string()));
    }

    use super::available_users;

    #[test]
    fn available_users_test_1() {
    	let cm = fixture();
    	let avail = available_users(&cm, "a".to_string());
    	assert!(avail.contains(&"b".to_string()));
    	assert!(avail.contains(&"c".to_string()));
    	assert!(avail.contains(&"d".to_string()));
    	assert!(avail.contains(&"e".to_string()));
    }

    #[test]
    fn available_users_test_2() {
    	let mut cm = fixture();

    	// Set c and d as partners
    	cm.get_mut(&"c".to_string()).unwrap().partner = Some("d".to_string());
    	cm.get_mut(&"d".to_string()).unwrap().partner = Some("c".to_string());

    	let avail = available_users(&cm, "a".to_string());
    	assert!(avail.contains(&"b".to_string()));
    	assert!(!avail.contains(&"c".to_string()));
    	assert!(!avail.contains(&"d".to_string()));
    	assert!(avail.contains(&"e".to_string()));
    }

    #[test]
    fn available_users_test_3_blocking() {
        let mut cm = fixture();

        // a blocks b
        cm.get_mut(&"a".to_string()).unwrap().blocked_users.push("b".to_string());

        // a asks for available users
        let avail = available_users(&cm, "a".to_string());

        // b not listed anymore
        assert!(!avail.contains(&"b".to_string()));
        assert!(avail.contains(&"c".to_string()));
        assert!(avail.contains(&"d".to_string()));
        assert!(avail.contains(&"e".to_string()));
    }

    #[test]
    fn available_users_test_4_blocking() {
        let mut cm = fixture();

        // a blocks b
        cm.get_mut(&"a".to_string()).unwrap().blocked_users.push("b".to_string());

        // b asks for available users
        let avail = available_users(&cm, "b".to_string());

        // a not listed anymore
        assert!(!avail.contains(&"a".to_string()));
        assert!(avail.contains(&"c".to_string()));
        assert!(avail.contains(&"d".to_string()));
        assert!(avail.contains(&"e".to_string()));
    }

    #[test]
    fn available_users_test_5_blocking() {
        let mut cm = fixture();

        // a blocks everyone
        cm.get_mut(&"a".to_string()).unwrap().blocked_users.push("b".to_string());
        cm.get_mut(&"a".to_string()).unwrap().blocked_users.push("c".to_string());
        cm.get_mut(&"a".to_string()).unwrap().blocked_users.push("d".to_string());
        cm.get_mut(&"a".to_string()).unwrap().blocked_users.push("e".to_string());

        // a asks for available users
        let avail = available_users(&cm, "a".to_string());

        // nobody listed as available
        assert_eq!(0, avail.len());
    }

    use super::quit_conversation;

    #[test]
    fn quit_conversation_test_1() {
        let mut cm = fixture();

        // Set a and b as partners
        cm.get_mut(&"a".to_string()).unwrap().partner = Some("b".to_string());
        cm.get_mut(&"b".to_string()).unwrap().partner = Some("a".to_string());

        quit_conversation(&mut cm, "a".to_string());

        assert_eq!(None, cm.get(&"a".to_string()).unwrap().partner);
        assert_eq!(Some("a".to_string()), cm.get(&"b".to_string()).unwrap().partner);
    }

    #[test]
    fn quit_conversation_test_2() {
        let mut cm = fixture();

        // Set a and b as partners
        cm.get_mut(&"a".to_string()).unwrap().partner = Some("b".to_string());
        cm.get_mut(&"b".to_string()).unwrap().partner = Some("a".to_string());

        // Set c and d as partners
        cm.get_mut(&"c".to_string()).unwrap().partner = Some("d".to_string());
        cm.get_mut(&"d".to_string()).unwrap().partner = Some("c".to_string());

        quit_conversation(&mut cm, "a".to_string());
        quit_conversation(&mut cm, "b".to_string());

        assert_eq!(None, cm.get(&"a".to_string()).unwrap().partner);
        assert_eq!(None, cm.get(&"b".to_string()).unwrap().partner);
        assert_eq!(Some("d".to_string()), cm.get(&"c".to_string()).unwrap().partner);
        assert_eq!(Some("c".to_string()), cm.get(&"d".to_string()).unwrap().partner);
    }

    #[test]
    fn quit_conversation_test_3() {
        let mut cm = fixture();

        // Set a and b as partners
        cm.get_mut(&"a".to_string()).unwrap().partner = Some("b".to_string());
        cm.get_mut(&"b".to_string()).unwrap().partner = Some("a".to_string());

        quit_conversation(&mut cm, "a".to_string());

        // Set a and c as partners
        cm.get_mut(&"a".to_string()).unwrap().partner = Some("c".to_string());
        cm.get_mut(&"c".to_string()).unwrap().partner = Some("a".to_string());

        quit_conversation(&mut cm, "b".to_string());

        assert_eq!(Some("c".to_string()), cm.get(&"a".to_string()).unwrap().partner);
        assert_eq!(None, cm.get(&"b".to_string()).unwrap().partner);
        assert_eq!(Some("a".to_string()), cm.get(&"c".to_string()).unwrap().partner);
    }

	fn fixture() -> ChatMap {
        let mut cm = ChatMap::new();
        let (sender_to_a, _) = channel();
        cm.insert("a".to_string(), ClientInfo{
            partner: None,
            sender_to_client: sender_to_a,
            blocked_users: Vec::new()
        });
        let (sender_to_b, _) = channel();
        cm.insert("b".to_string(), ClientInfo{
            partner: None,
            sender_to_client: sender_to_b,
            blocked_users: Vec::new()
        });
        let (sender_to_c, _) = channel();
        cm.insert("c".to_string(), ClientInfo{
            partner: None,
            sender_to_client: sender_to_c,
            blocked_users: Vec::new()
        });
        let (sender_to_d, _) = channel();
        cm.insert("d".to_string(), ClientInfo{
            partner: None,
            sender_to_client: sender_to_d,
            blocked_users: Vec::new()
        });
        let (sender_to_e, _) = channel();
        cm.insert("e".to_string(), ClientInfo{
            partner: None,
            sender_to_client: sender_to_e,
            blocked_users: Vec::new()
        });
        cm
    }
}<|endoftext|>


<commit_before>use std::io::Cursor;

use byteorder::BigEndian;

struct Encode<I> {
    iter: I,
    cur: Cursor<Vec<u8>>,
}

impl<'a, I> Encode<I>
where
    I: Iterator<Item = &'a [u8]>,
{
    fn is_empty(&self) -> bool {
        self.cur.position() == self.cur.get_ref().len() as u64
    }

    fn pull(&mut self) -> std::io::Result<()> {
        use std::io::Write as _;
        use byteorder::WriteBytesExt as _;

        let data = match self.iter.next() {
            Some(data) => data,
            None => return Ok(()),
        };

        self.cur.get_mut().clear();
        self.cur.set_position(0);

        self.cur.write_u64::<BigEndian>(data.len() as u64)?;
        self.cur.write_all(data)?;

        Ok(())
    }
}

impl<'a, I> std::io::Read for Encode<I>
where
    I: Iterator<Item = &'a [u8]>,
{
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        if self.is_empty() {
            self.pull()?;
        }

        self.cur.read(buf)
    }
}

struct Decode<R> {
    buf: R,
}

impl<R: std::io::Read> Decode<R> {

    fn read_len(&mut self) -> std::io::Result<Option<usize>> {
        use byteorder::ReadBytesExt as _;

        let mut buf = [0; 8];
        match self.buf.read(&mut buf[..])? {
            8 => (),
            0 => return Ok(None),
            _ => return Err(SizeTagError.into()),
        }

        let len = (&buf[..]).read_u64::<BigEndian>()? as usize;
        Ok(Some(len))
    }
}

impl<R: std::io::Read> Iterator for Decode<R> {

    type Item = std::io::Result<Vec<u8>>;

    fn next(&mut self) -> Option<std::io::Result<Vec<u8>>> {
        let len = match self.read_len() {
            Ok(Some(len)) => len,
            Ok(None) => return None,
            Err(error) => return Some(Err(error)),
        };

        let mut buf = vec!(0; len);
        match self.buf.read_exact(&mut buf[..]) {
            Ok(()) => (),
            Err(error) => return Some(Err(error)),
        }

        Some(Ok(buf))
    }
}

#[derive(Debug)]
struct SizeTagError;

impl std::fmt::Display for SizeTagError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(fmt, "incorrect length of the size tag")
    }
}

impl std::error::Error for SizeTagError {
}

impl From<SizeTagError> for std::io::Error {

    fn from(error: SizeTagError) -> std::io::Error {
        std::io::Error::new(std::io::ErrorKind::InvalidData, error)
    }
}
<commit_msg>Add wrappers for chunked encoding and decoding.<commit_after>use std::io::Cursor;

use byteorder::BigEndian;

pub fn encode<'a, I>(iter: I) -> Encode<I>
where
    I: Iterator<Item = &'a [u8]>,
{
    Encode {
        iter: iter,
        cur: Cursor::new(vec!()),
    }
}

pub fn decode<R>(buf: R) -> Decode<R>
where
    R: std::io::Read,
{
    Decode {
        buf: buf,
    }
}

pub struct Encode<I> {
    iter: I,
    cur: Cursor<Vec<u8>>,
}

impl<'a, I> Encode<I>
where
    I: Iterator<Item = &'a [u8]>,
{
    fn is_empty(&self) -> bool {
        self.cur.position() == self.cur.get_ref().len() as u64
    }

    fn pull(&mut self) -> std::io::Result<()> {
        use std::io::Write as _;
        use byteorder::WriteBytesExt as _;

        let data = match self.iter.next() {
            Some(data) => data,
            None => return Ok(()),
        };

        self.cur.get_mut().clear();
        self.cur.set_position(0);

        self.cur.write_u64::<BigEndian>(data.len() as u64)?;
        self.cur.write_all(data)?;

        Ok(())
    }
}

impl<'a, I> std::io::Read for Encode<I>
where
    I: Iterator<Item = &'a [u8]>,
{
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        if self.is_empty() {
            self.pull()?;
        }

        self.cur.read(buf)
    }
}

pub struct Decode<R> {
    buf: R,
}

impl<R: std::io::Read> Decode<R> {

    fn read_len(&mut self) -> std::io::Result<Option<usize>> {
        use byteorder::ReadBytesExt as _;

        let mut buf = [0; 8];
        match self.buf.read(&mut buf[..])? {
            8 => (),
            0 => return Ok(None),
            _ => return Err(SizeTagError.into()),
        }

        let len = (&buf[..]).read_u64::<BigEndian>()? as usize;
        Ok(Some(len))
    }
}

impl<R: std::io::Read> Iterator for Decode<R> {

    type Item = std::io::Result<Vec<u8>>;

    fn next(&mut self) -> Option<std::io::Result<Vec<u8>>> {
        let len = match self.read_len() {
            Ok(Some(len)) => len,
            Ok(None) => return None,
            Err(error) => return Some(Err(error)),
        };

        let mut buf = vec!(0; len);
        match self.buf.read_exact(&mut buf[..]) {
            Ok(()) => (),
            Err(error) => return Some(Err(error)),
        }

        Some(Ok(buf))
    }
}

#[derive(Debug)]
struct SizeTagError;

impl std::fmt::Display for SizeTagError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(fmt, "incorrect length of the size tag")
    }
}

impl std::error::Error for SizeTagError {
}

impl From<SizeTagError> for std::io::Error {

    fn from(error: SizeTagError) -> std::io::Error {
        std::io::Error::new(std::io::ErrorKind::InvalidData, error)
    }
}
<|endoftext|>


<commit_before>use std::fmt;
/// We re-export winit so it's easy for people to use the same version as we are
/// without having to mess around figuring it out.
pub use winit;

use crate::audio;
use crate::conf;
use crate::error::GameResult;
use crate::filesystem::Filesystem;
use crate::graphics;
use crate::input::{gamepad, keyboard, mouse};
use crate::timer;

/// A `Context` is an object that holds on to global resources.
/// It basically tracks hardware state such as the screen, audio
/// system, timers, and so on.  Generally this type can **not**
/// be shared/sent between threads and only one `Context` can exist at a time.  Trying
/// to create a second one will fail.  It is fine to drop a `Context`
/// and create a new one, but this will also close and re-open your
/// game's window.
///
/// Most functions that interact with the hardware, for instance
/// drawing things, playing sounds, or loading resources (which then
/// need to be transformed into a format the hardware likes) will need
/// to access the `Context`.  It is an error to create some type that
/// relies upon a `Context`, such as `Image`, and then drop the `Context`
/// and try to draw the old `Image` with the new `Context`.  Most types
/// include checks to make this panic in debug mode, but it's not perfect.
///
/// All fields in this struct are basically undocumented features,
/// only here to make it easier to debug, or to let advanced users
/// hook into the guts of ggez and make it do things it normally
/// can't.  Most users shouldn't need to touch these things directly,
/// since implementation details may change without warning.  The
/// public and stable API is `ggez`'s module-level functions and
/// types.
pub struct Context {
    /// Filesystem state
    pub filesystem: Filesystem,
    /// Graphics state
    pub(crate) gfx_context: crate::graphics::context::GraphicsContext,
    /// Timer state
    pub timer_context: timer::TimeContext,
    /// Audio context
    pub audio_context: Box<dyn audio::AudioContext>,
    /// Keyboard context
    pub keyboard_context: keyboard::KeyboardContext,
    /// Mouse context
    pub mouse_context: mouse::MouseContext,
    /// Gamepad context
    pub gamepad_context: Box<dyn gamepad::GamepadContext>,

    /// The Conf object the Context was created with.
    /// It's here just so that we can see the original settings,
    /// updating it will have no effect.
    pub(crate) conf: conf::Conf,
    /// Controls whether or not the event loop should be running.
    /// Set this with `ggez::event::quit()`.
    pub continuing: bool,

    /// Context-specific unique ID.
    /// Compiles to nothing in release mode, and so
    /// vanishes; meanwhile we get dead-code warnings.
    #[allow(dead_code)]
    debug_id: DebugId,
}

impl fmt::Debug for Context {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<Context: {:p}>", self)
    }
}

impl Context {
    /// Tries to create a new Context using settings from the given [`Conf`](../conf/struct.Conf.html) object.
    /// Usually called by [`ContextBuilder::build()`](struct.ContextBuilder.html#method.build).
    fn from_conf(
        conf: conf::Conf,
        mut fs: Filesystem,
    ) -> GameResult<(Context, winit::event_loop::EventLoop<()>)> {
        let debug_id = DebugId::new();
        let audio_context: Box<dyn audio::AudioContext> = if conf.modules.audio {
            Box::new(audio::RodioAudioContext::new()?)
        } else {
            Box::new(audio::NullAudioContext::default())
        };
        let events_loop = winit::event_loop::EventLoop::new();
        let timer_context = timer::TimeContext::new();
        let backend_spec = graphics::GlBackendSpec::from(conf.backend);
        let graphics_context = graphics::context::GraphicsContext::new(
            &mut fs,
            &events_loop,
            &conf.window_setup,
            conf.window_mode,
            backend_spec,
            debug_id,
        )?;
        let mouse_context = mouse::MouseContext::new();
        let keyboard_context = keyboard::KeyboardContext::new();
        let gamepad_context: Box<dyn gamepad::GamepadContext> = if conf.modules.gamepad {
            Box::new(gamepad::GilrsGamepadContext::new()?)
        } else {
            Box::new(gamepad::NullGamepadContext::default())
        };

        let ctx = Context {
            conf,
            filesystem: fs,
            gfx_context: graphics_context,
            continuing: true,
            timer_context,
            audio_context,
            keyboard_context,
            gamepad_context,
            mouse_context,

            debug_id,
        };

        Ok((ctx, events_loop))
    }
}

use std::borrow::Cow;
use std::path;

/// A builder object for creating a [`Context`](struct.Context.html).
#[derive(Debug, Clone, PartialEq)]
pub struct ContextBuilder {
    pub(crate) game_id: String,
    pub(crate) author: String,
    pub(crate) conf: conf::Conf,
    pub(crate) paths: Vec<path::PathBuf>,
    pub(crate) memory_zip_files: Vec<Cow<'static, [u8]>>,
    pub(crate) load_conf_file: bool,
}

impl ContextBuilder {
    /// Create a new `ContextBuilder` with default settings.
    pub fn new(game_id: &str, author: &str) -> Self {
        Self {
            game_id: game_id.to_string(),
            author: author.to_string(),
            conf: conf::Conf::default(),
            paths: vec![],
            memory_zip_files: vec![],
            load_conf_file: true,
        }
    }

    /// Sets the window setup settings.
    pub fn window_setup(mut self, setup: conf::WindowSetup) -> Self {
        self.conf.window_setup = setup;
        self
    }

    /// Sets the window mode settings.
    pub fn window_mode(mut self, mode: conf::WindowMode) -> Self {
        self.conf.window_mode = mode;
        self
    }

    /// Sets the graphics backend.
    pub fn backend(mut self, backend: conf::Backend) -> Self {
        self.conf.backend = backend;
        self
    }

    /// Sets the modules configuration.
    pub fn modules(mut self, modules: conf::ModuleConf) -> Self {
        self.conf.modules = modules;
        self
    }

    /// Sets all the config options, overriding any previous
    /// ones from [`window_setup()`](#method.window_setup),
    /// [`window_mode()`](#method.window_mode), and
    /// [`backend()`](#method.backend).  These are used as
    /// defaults and are overridden by any external config
    /// file found.
    pub fn default_conf(mut self, conf: conf::Conf) -> Self {
        self.conf = conf;
        self
    }

    /// Add a new read-only filesystem path to the places to search
    /// for resources.
    pub fn add_resource_path<T>(mut self, path: T) -> Self
    where
        T: Into<path::PathBuf>,
    {
        self.paths.push(path.into());
        self
    }

    /// Add a new zip file from bytes whose contents will be searched
    /// for resources. The zip file will be stored in-memory.
    /// You can pass it a static slice, a `Vec` of bytes, etc.
    ///
    /// ```ignore
    /// use ggez::context::ContextBuilder;
    /// let _ = ContextBuilder::new()
    ///     .add_zipfile_bytes(include_bytes!("../resources.zip").to_vec())
    ///     .build();
    /// ```
    pub fn add_zipfile_bytes<B>(mut self, bytes: B) -> Self
    where
        B: Into<Cow<'static, [u8]>>,
    {
        let cow = bytes.into();
        self.memory_zip_files.push(cow);
        self
    }

    /// Specifies whether or not to load the `conf.toml` file if it
    /// exists and use its settings to override the provided values.
    /// Defaults to `true` which is usually what you want, but being
    /// able to fiddle with it is sometimes useful for debugging.
    pub fn with_conf_file(mut self, load_conf_file: bool) -> Self {
        self.load_conf_file = load_conf_file;
        self
    }

    /// Build the `Context`.
    pub fn build(self) -> GameResult<(Context, winit::event_loop::EventLoop<()>)> {
        let mut fs = Filesystem::new(
            self.game_id.as_ref(),
            self.author.as_ref(),
            "resources",
            "resources.zip",
        )?;

        for path in &self.paths {
            fs.mount(path, true);
        }

        for zipfile_bytes in self.memory_zip_files {
            fs.add_zip_file(std::io::Cursor::new(zipfile_bytes))?;
        }

        let config = if self.load_conf_file {
            fs.read_config().unwrap_or(self.conf)
        } else {
            self.conf
        };

        Context::from_conf(config, fs)
    }
}

#[cfg(debug_assertions)]
use std::sync::atomic::{AtomicU32, Ordering};
#[cfg(debug_assertions)]
static DEBUG_ID_COUNTER: AtomicU32 = AtomicU32::new(0);

/// This is a type that contains a unique ID for each `Context` and
/// is contained in each thing created from the `Context` which
/// becomes invalid when the `Context` goes away (for example, `Image` because
/// it contains texture handles).  When compiling without assertions
/// (in release mode) it is replaced with a zero-size type, compiles
/// down to nothing, disappears entirely with a puff of optimization logic.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg(debug_assertions)]
pub(crate) struct DebugId(u32);
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg(not(debug_assertions))]
pub(crate) struct DebugId;

#[cfg(debug_assertions)]
impl DebugId {
    pub fn new() -> Self {
        let id = DEBUG_ID_COUNTER.fetch_add(1, Ordering::SeqCst);
        // fetch_add() wraps on overflow so we check for overflow explicitly.
        // JUST IN CASE YOU TRY TO CREATE 2^32 CONTEXTS IN ONE PROGRAM!  muahahahahaaa
        assert!(DEBUG_ID_COUNTER.load(Ordering::SeqCst) > id);
        DebugId(id)
    }

    pub fn get(ctx: &Context) -> Self {
        DebugId(ctx.debug_id.0)
    }

    #[allow(clippy::trivially_copy_pass_by_ref)]
    pub fn assert(&self, ctx: &Context) {
        if *self != ctx.debug_id {
            panic!("Tried to use a resource with a Context that did not create it; this should never happen!");
        }
    }
}

#[cfg(not(debug_assertions))]
impl DebugId {
    pub fn new() -> Self {
        DebugId
    }

    pub fn get(_ctx: &Context) -> Self {
        DebugId
    }

    pub fn assert(&self, _ctx: &Context) {
        // Do nothing.
    }
}
<commit_msg>Allow ContextBuilder to rename resources and resources.zip<commit_after>use std::fmt;
/// We re-export winit so it's easy for people to use the same version as we are
/// without having to mess around figuring it out.
pub use winit;

use crate::audio;
use crate::conf;
use crate::error::GameResult;
use crate::filesystem::Filesystem;
use crate::graphics;
use crate::input::{gamepad, keyboard, mouse};
use crate::timer;

/// A `Context` is an object that holds on to global resources.
/// It basically tracks hardware state such as the screen, audio
/// system, timers, and so on.  Generally this type can **not**
/// be shared/sent between threads and only one `Context` can exist at a time.  Trying
/// to create a second one will fail.  It is fine to drop a `Context`
/// and create a new one, but this will also close and re-open your
/// game's window.
///
/// Most functions that interact with the hardware, for instance
/// drawing things, playing sounds, or loading resources (which then
/// need to be transformed into a format the hardware likes) will need
/// to access the `Context`.  It is an error to create some type that
/// relies upon a `Context`, such as `Image`, and then drop the `Context`
/// and try to draw the old `Image` with the new `Context`.  Most types
/// include checks to make this panic in debug mode, but it's not perfect.
///
/// All fields in this struct are basically undocumented features,
/// only here to make it easier to debug, or to let advanced users
/// hook into the guts of ggez and make it do things it normally
/// can't.  Most users shouldn't need to touch these things directly,
/// since implementation details may change without warning.  The
/// public and stable API is `ggez`'s module-level functions and
/// types.
pub struct Context {
    /// Filesystem state
    pub filesystem: Filesystem,
    /// Graphics state
    pub(crate) gfx_context: crate::graphics::context::GraphicsContext,
    /// Timer state
    pub timer_context: timer::TimeContext,
    /// Audio context
    pub audio_context: Box<dyn audio::AudioContext>,
    /// Keyboard context
    pub keyboard_context: keyboard::KeyboardContext,
    /// Mouse context
    pub mouse_context: mouse::MouseContext,
    /// Gamepad context
    pub gamepad_context: Box<dyn gamepad::GamepadContext>,

    /// The Conf object the Context was created with.
    /// It's here just so that we can see the original settings,
    /// updating it will have no effect.
    pub(crate) conf: conf::Conf,
    /// Controls whether or not the event loop should be running.
    /// Set this with `ggez::event::quit()`.
    pub continuing: bool,

    /// Context-specific unique ID.
    /// Compiles to nothing in release mode, and so
    /// vanishes; meanwhile we get dead-code warnings.
    #[allow(dead_code)]
    debug_id: DebugId,
}

impl fmt::Debug for Context {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<Context: {:p}>", self)
    }
}

impl Context {
    /// Tries to create a new Context using settings from the given [`Conf`](../conf/struct.Conf.html) object.
    /// Usually called by [`ContextBuilder::build()`](struct.ContextBuilder.html#method.build).
    fn from_conf(
        conf: conf::Conf,
        mut fs: Filesystem,
    ) -> GameResult<(Context, winit::event_loop::EventLoop<()>)> {
        let debug_id = DebugId::new();
        let audio_context: Box<dyn audio::AudioContext> = if conf.modules.audio {
            Box::new(audio::RodioAudioContext::new()?)
        } else {
            Box::new(audio::NullAudioContext::default())
        };
        let events_loop = winit::event_loop::EventLoop::new();
        let timer_context = timer::TimeContext::new();
        let backend_spec = graphics::GlBackendSpec::from(conf.backend);
        let graphics_context = graphics::context::GraphicsContext::new(
            &mut fs,
            &events_loop,
            &conf.window_setup,
            conf.window_mode,
            backend_spec,
            debug_id,
        )?;
        let mouse_context = mouse::MouseContext::new();
        let keyboard_context = keyboard::KeyboardContext::new();
        let gamepad_context: Box<dyn gamepad::GamepadContext> = if conf.modules.gamepad {
            Box::new(gamepad::GilrsGamepadContext::new()?)
        } else {
            Box::new(gamepad::NullGamepadContext::default())
        };

        let ctx = Context {
            conf,
            filesystem: fs,
            gfx_context: graphics_context,
            continuing: true,
            timer_context,
            audio_context,
            keyboard_context,
            gamepad_context,
            mouse_context,

            debug_id,
        };

        Ok((ctx, events_loop))
    }
}

use std::borrow::Cow;
use std::path;

/// A builder object for creating a [`Context`](struct.Context.html).
#[derive(Debug, Clone, PartialEq)]
pub struct ContextBuilder {
    pub(crate) game_id: String,
    pub(crate) author: String,
    pub(crate) conf: conf::Conf,
    pub(crate) resources_dir_name: String,
    pub(crate) resources_zip_name: String,
    pub(crate) paths: Vec<path::PathBuf>,
    pub(crate) memory_zip_files: Vec<Cow<'static, [u8]>>,
    pub(crate) load_conf_file: bool,
}

impl ContextBuilder {
    /// Create a new `ContextBuilder` with default settings.
    pub fn new(game_id: &str, author: &str) -> Self {
        Self {
            game_id: game_id.to_string(),
            author: author.to_string(),
            conf: conf::Conf::default(),
            resources_dir_name: "resources".to_string(),
            resources_zip_name: "resources.zip".to_string(),
            paths: vec![],
            memory_zip_files: vec![],
            load_conf_file: true,
        }
    }

    /// Sets the window setup settings.
    pub fn window_setup(mut self, setup: conf::WindowSetup) -> Self {
        self.conf.window_setup = setup;
        self
    }

    /// Sets the window mode settings.
    pub fn window_mode(mut self, mode: conf::WindowMode) -> Self {
        self.conf.window_mode = mode;
        self
    }

    /// Sets the graphics backend.
    pub fn backend(mut self, backend: conf::Backend) -> Self {
        self.conf.backend = backend;
        self
    }

    /// Sets the modules configuration.
    pub fn modules(mut self, modules: conf::ModuleConf) -> Self {
        self.conf.modules = modules;
        self
    }

    /// Sets all the config options, overriding any previous
    /// ones from [`window_setup()`](#method.window_setup),
    /// [`window_mode()`](#method.window_mode), and
    /// [`backend()`](#method.backend).  These are used as
    /// defaults and are overridden by any external config
    /// file found.
    pub fn default_conf(mut self, conf: conf::Conf) -> Self {
        self.conf = conf;
        self
    }

    /// Sets resources dir name.
    /// Default resources dir name is `resources`.
    pub fn change_resources_dir_name(mut self, new_name: impl ToString) -> Self {
        self.resources_dir_name = new_name.to_string();
        self
    }

    /// Sets resources zip name.
    /// Default resources dir name is `resources.zip`.
    pub fn change_resources_zip_name(mut self, new_name: impl ToString) -> Self {
        self.resources_zip_name = new_name.to_string();
        self
    }

    /// Add a new read-only filesystem path to the places to search
    /// for resources.
    pub fn add_resource_path<T>(mut self, path: T) -> Self
    where
        T: Into<path::PathBuf>,
    {
        self.paths.push(path.into());
        self
    }

    /// Add a new zip file from bytes whose contents will be searched
    /// for resources. The zip file will be stored in-memory.
    /// You can pass it a static slice, a `Vec` of bytes, etc.
    ///
    /// ```ignore
    /// use ggez::context::ContextBuilder;
    /// let _ = ContextBuilder::new()
    ///     .add_zipfile_bytes(include_bytes!("../resources.zip").to_vec())
    ///     .build();
    /// ```
    pub fn add_zipfile_bytes<B>(mut self, bytes: B) -> Self
    where
        B: Into<Cow<'static, [u8]>>,
    {
        let cow = bytes.into();
        self.memory_zip_files.push(cow);
        self
    }

    /// Specifies whether or not to load the `conf.toml` file if it
    /// exists and use its settings to override the provided values.
    /// Defaults to `true` which is usually what you want, but being
    /// able to fiddle with it is sometimes useful for debugging.
    pub fn with_conf_file(mut self, load_conf_file: bool) -> Self {
        self.load_conf_file = load_conf_file;
        self
    }

    /// Build the `Context`.
    pub fn build(self) -> GameResult<(Context, winit::event_loop::EventLoop<()>)> {
        let mut fs = Filesystem::new(
            self.game_id.as_ref(),
            self.author.as_ref(),
            &self.resources_dir_name,
            &self.resources_zip_name,
        )?;

        for path in &self.paths {
            fs.mount(path, true);
        }

        for zipfile_bytes in self.memory_zip_files {
            fs.add_zip_file(std::io::Cursor::new(zipfile_bytes))?;
        }

        let config = if self.load_conf_file {
            fs.read_config().unwrap_or(self.conf)
        } else {
            self.conf
        };

        Context::from_conf(config, fs)
    }
}

#[cfg(debug_assertions)]
use std::sync::atomic::{AtomicU32, Ordering};
#[cfg(debug_assertions)]
static DEBUG_ID_COUNTER: AtomicU32 = AtomicU32::new(0);

/// This is a type that contains a unique ID for each `Context` and
/// is contained in each thing created from the `Context` which
/// becomes invalid when the `Context` goes away (for example, `Image` because
/// it contains texture handles).  When compiling without assertions
/// (in release mode) it is replaced with a zero-size type, compiles
/// down to nothing, disappears entirely with a puff of optimization logic.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg(debug_assertions)]
pub(crate) struct DebugId(u32);
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg(not(debug_assertions))]
pub(crate) struct DebugId;

#[cfg(debug_assertions)]
impl DebugId {
    pub fn new() -> Self {
        let id = DEBUG_ID_COUNTER.fetch_add(1, Ordering::SeqCst);
        // fetch_add() wraps on overflow so we check for overflow explicitly.
        // JUST IN CASE YOU TRY TO CREATE 2^32 CONTEXTS IN ONE PROGRAM!  muahahahahaaa
        assert!(DEBUG_ID_COUNTER.load(Ordering::SeqCst) > id);
        DebugId(id)
    }

    pub fn get(ctx: &Context) -> Self {
        DebugId(ctx.debug_id.0)
    }

    #[allow(clippy::trivially_copy_pass_by_ref)]
    pub fn assert(&self, ctx: &Context) {
        if *self != ctx.debug_id {
            panic!("Tried to use a resource with a Context that did not create it; this should never happen!");
        }
    }
}

#[cfg(not(debug_assertions))]
impl DebugId {
    pub fn new() -> Self {
        DebugId
    }

    pub fn get(_ctx: &Context) -> Self {
        DebugId
    }

    pub fn assert(&self, _ctx: &Context) {
        // Do nothing.
    }
}
<|endoftext|>


<commit_before>use Result;
use error::Error::{UnknownWord, SyntaxError};
use stack::Stack;
use std::result::Result::{Ok, Err};
use word::Word;
use word::WordKind::{Builtin, Words};

#[deriving(Default)]
pub struct Context {
    stack: Stack,
    dict: Vec<Word>,
    compiling_word: Option<Word>,
}

impl Context {
    pub fn new() -> Context {
        Context {
            stack: Stack::new(),
            dict: Vec::new(),
            compiling_word: None,
        }
    }

    pub fn add_word(&mut self, word: Word) {
        self.dict.push(word);
    }

    fn real_run_word(dict: &Vec<Word>, stack: &mut Stack,
                     command: &str) -> Result {
        match dict.iter().find(|word| word.command == command) {
            Some(word) => match word.kind {
                    Builtin(ref f) => try!((**f).call((stack,))),
                    Words(ref ws) => for w in ws.iter() {
                        try!(Context::real_run_word(dict, stack, w.as_slice()));
                    },
            },
            None => {
                let i = try!(command.parse().ok_or(UnknownWord));
                stack.push(i);
            },
        }
        Ok(())
    }

    pub fn run_word(&mut self, command: &str) -> Result {
        Context::real_run_word(&self.dict, &mut self.stack, command)
    }

    pub fn parse_line(&mut self, line: &str) -> Result {
        let mut tokens = line.trim_right_chars('\n').words();
        loop {
            let token = match tokens.next() {
                Some(t) => t,
                None => break,
            };
            match token {
                ":" => {
                    match self.compiling_word {
                        None => {
                            let command = try!(tokens.next().ok_or(SyntaxError));
                            self.compiling_word = Some(Word {
                                command: String::from_str(command),
                                kind: Words(Vec::new())
                            });
                        }
                        Some(..) => return Err(SyntaxError),
                    }
                },
                ";" => {
                    match self.compiling_word.take() {
                        Some(word) => {
                            self.dict.push(word);
                        },
                        None => return Err(SyntaxError),
                    }
                },
                word => {
                    match self.compiling_word {
                        Some(ref mut partial_word) => {
                            match partial_word.kind {
                                Words(ref mut ws) => ws.push(String::from_str(word)),
                                _ => panic!("compiling_word not Words kind"),
                            }
                        },
                        None => try!(self.run_word(word)),
                    }
                },
            }
        }
        debug!("stack={}", self.stack);
        Ok(())
    }
}
<commit_msg>Fix deprecation warning<commit_after>use Result;
use error::Error::{UnknownWord, SyntaxError};
use stack::Stack;
use std::result::Result::{Ok, Err};
use word::Word;
use word::WordKind::{Builtin, Words};

#[deriving(Default)]
pub struct Context {
    stack: Stack,
    dict: Vec<Word>,
    compiling_word: Option<Word>,
}

impl Context {
    pub fn new() -> Context {
        Context {
            stack: Stack::new(),
            dict: Vec::new(),
            compiling_word: None,
        }
    }

    pub fn add_word(&mut self, word: Word) {
        self.dict.push(word);
    }

    fn real_run_word(dict: &Vec<Word>, stack: &mut Stack,
                     command: &str) -> Result {
        match dict.iter().find(|word| word.command == command) {
            Some(word) => match word.kind {
                    Builtin(ref f) => try!((**f).call((stack,))),
                    Words(ref ws) => for w in ws.iter() {
                        try!(Context::real_run_word(dict, stack, w.as_slice()));
                    },
            },
            None => {
                let i = try!(command.parse().ok_or(UnknownWord));
                stack.push(i);
            },
        }
        Ok(())
    }

    pub fn run_word(&mut self, command: &str) -> Result {
        Context::real_run_word(&self.dict, &mut self.stack, command)
    }

    pub fn parse_line(&mut self, line: &str) -> Result {
        let mut tokens = line.trim_right_matches('\n').words();
        loop {
            let token = match tokens.next() {
                Some(t) => t,
                None => break,
            };
            match token {
                ":" => {
                    match self.compiling_word {
                        None => {
                            let command = try!(tokens.next().ok_or(SyntaxError));
                            self.compiling_word = Some(Word {
                                command: String::from_str(command),
                                kind: Words(Vec::new())
                            });
                        }
                        Some(..) => return Err(SyntaxError),
                    }
                },
                ";" => {
                    match self.compiling_word.take() {
                        Some(word) => {
                            self.dict.push(word);
                        },
                        None => return Err(SyntaxError),
                    }
                },
                word => {
                    match self.compiling_word {
                        Some(ref mut partial_word) => {
                            match partial_word.kind {
                                Words(ref mut ws) => ws.push(String::from_str(word)),
                                _ => panic!("compiling_word not Words kind"),
                            }
                        },
                        None => try!(self.run_word(word)),
                    }
                },
            }
        }
        debug!("stack={}", self.stack);
        Ok(())
    }
}
<|endoftext|>