<commit_before>use gen::GenError;

mod text;
mod binary;
pub use self::text::*;
pub use self::binary::*;

#[derive(Clone,Copy,Debug,PartialEq)]
pub enum Serialized {
  Done,
  Continue,
}

pub trait Serializer {
  fn serialize(&mut self, output: &mut [u8]) -> Result<(usize, Serialized), GenError>;

  #[inline(always)]
  fn then<T>(self, next: T) -> Then<Self, T>
    where
      Self: Sized,
      T: Serializer
  {
    Then::new(self, next)
  }
}

pub trait Reset {
  fn reset(&mut self) -> bool;
}

pub fn or<T,U>(t: Option<T>, u: U) -> Or<T, U>
  where
    T: Serializer,
    U: Serializer
{
  Or::new(t, u)
}

#[derive(Debug)]
pub struct Empty;

impl Serializer for Empty {
  #[inline(always)]
  fn serialize<'b, 'c>(&'b mut self, _output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    Ok((0, Serialized::Done))
  }
}

impl Reset for Empty {
  fn reset(&mut self) -> bool {
    true
  }
}

#[inline(always)]
pub fn empty() -> Empty {
  Empty
}

#[derive(Debug)]
pub struct Skip(usize);

impl Serializer for Skip {
  #[inline(always)]
  fn serialize<'b, 'c>(&'b mut self, output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    if output.len() < self.0 {
      Ok((0, Serialized::Continue))
    } else {
      Ok((self.0, Serialized::Done))
    }
  }
}

impl Reset for Skip {
  fn reset(&mut self) -> bool {
    true
  }
}

#[inline(always)]
pub fn skip(sz: usize) -> Skip {
  Skip(sz)
}

impl<S: ?Sized + Serializer> Serializer for Box<S> {
  #[inline(always)]
  fn serialize<'b, 'c>(&'b mut self, output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    (**self).serialize(output)
  }
}

pub struct Then<A, B> {
  a: Option<A>,
  b: B,
}

impl<A:Serializer, B:Serializer> Then<A, B> {
  #[inline(always)]
  pub fn new(a: A, b: B) -> Self {
    Then {
      a: Some(a),
      b,
    }
  }
}

impl<A:Serializer, B:Serializer> Serializer for Then<A,B> {
  #[inline(always)]
  fn serialize<'b, 'c>(&'b mut self, output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    let mut i = 0;
    if let Some(mut a) = self.a.take() {
      match a.serialize(output)? {
        (index, Serialized::Continue) => {
          self.a = Some(a);
          return Ok((index, Serialized::Continue))
        },
        (index, Serialized::Done) => {
          i = index;
        }
      }
    }

    let sl = &mut output[i..];
    self.b.serialize(sl).map(|(index, res)| (index+i, res))
  }
}

pub struct Or<A, B> {
  a: Option<A>,
  b: B,
}

impl<A:Serializer, B:Serializer> Or<A, B> {
  #[inline(always)]
  pub fn new(a: Option<A>, b: B) -> Self {
    Or {
      a,
      b,
    }
  }
}

impl<A:Serializer, B:Serializer> Serializer for Or<A,B> {
  #[inline(always)]
  fn serialize<'b, 'c>(&'b mut self, output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    match &mut self.a {
      Some(ref mut a) => a.serialize(output),
      None => self.b.serialize(output)
    }
  }
}

impl<A:Serializer+Reset, B:Serializer+Reset> Reset for Or<A, B> {
  fn reset(&mut self) -> bool {
    self.a.as_mut().map(|a| a.reset()).unwrap_or(self.b.reset())
  }
}

pub struct All<T,It> {
  current: Option<T>,
  it: It,
}

impl<T: Serializer, It: Iterator<Item=T>> All<T, It> {
  #[inline(always)]
  pub fn new<IntoIt: IntoIterator<Item=T, IntoIter=It>>(it: IntoIt) -> Self {
    All {
      current: None,
      it: it.into_iter(),
    }
  }
}

impl<T: Serializer, It: Iterator<Item=T>> Serializer for All<T, It> {
  fn serialize<'b, 'c>(&'b mut self, output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    let mut index = 0;

    loop {
      let mut current = match self.current.take() {
        Some(s) => s,
        None => match self.it.next() {
          Some(s) => s,
          None => return Ok((index, Serialized::Done)),
        }
      };

      let sl = &mut output[index..];
      match current.serialize(sl)? {
        (i, Serialized::Continue) => {
          self.current = Some(current);
          return Ok((index + i, Serialized::Continue));
        },
        (i, Serialized::Done) => {
          index += i;
        },
      }
    }
  }
}

#[inline(always)]
pub fn all<T: Serializer, It: Iterator<Item=T>, IntoIt: IntoIterator<Item=T, IntoIter=It>>(it: IntoIt) -> All<T, It> {
  All::new(it)
}

pub struct SeparatedList<T,U,It> {
  current: Option<T>,
  it: It,
  separator: U,
  serialize_element: bool,
}

impl<T: Serializer, U: Serializer+Reset, It: Iterator<Item=T>> SeparatedList<T, U, It> {
  #[inline(always)]
  pub fn new<IntoIt: IntoIterator<Item=T, IntoIter=It>>(separator: U, it: IntoIt) -> Self {
    let mut it = it.into_iter();
    SeparatedList {
      current: it.next(),
      it,
      separator,
      serialize_element: true,
    }
  }
}

impl<T: Serializer, U: Serializer+Reset, It: Iterator<Item=T>> Serializer for SeparatedList<T, U, It> {
  fn serialize<'b, 'c>(&'b mut self, output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    let mut index = 0;

    loop {
      let sl = &mut output[index..];

      if self.serialize_element {
        let mut current = match self.current.take() {
          Some(s) => s,
          None => return Ok((index, Serialized::Done)),
        };

        match current.serialize(sl)? {
          (i, Serialized::Continue) => {
            self.current = Some(current);
            return Ok((index + i, Serialized::Continue));
          },
          (i, Serialized::Done) => {
            index += i;
          },
        }

        self.current = self.it.next();
        if self.current.is_some() {
          self.serialize_element = false;
        }
      } else {
        // serialize separator
        match self.separator.serialize(sl)? {
          (i, Serialized::Continue) => {
            return Ok((index + i, Serialized::Continue));
          },
          (i, Serialized::Done) => {
            index += i;
            self.serialize_element = true;
            self.separator.reset();
          },

        }
      }
    }
  }
}

impl Serializer for Fn(&mut [u8]) -> Result<(&mut [u8],usize),GenError> {
  fn serialize<'b, 'c>(&'b mut self, output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    match self(output) {
      Err(e) => Err(e),
      Ok((_, index)) => Ok((index, Serialized::Done)),
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use std::str::from_utf8;

  #[test]
  fn then_serializer() {
    let s1 = String::from("hello ");
    let sr1 = Slice::new(s1.as_str().as_bytes());

    let s2 = String::from("world!");
    let sr2 = s2.raw();//StrSerializer::new(s2.as_str());

    let mut sr = sr1.then(sr2);

    let mut mem: [u8; 4] = [0; 4];
    let s = &mut mem[..];

    assert_eq!(sr.serialize(s), Ok((4, Serialized::Continue)));
    assert_eq!(&s[..], b"hell");

    assert_eq!(sr.serialize(s), Ok((4, Serialized::Continue)));
    assert_eq!(&s[..], b"o wo");

    assert_eq!(sr.serialize(s), Ok((4, Serialized::Done)));
    assert_eq!(&s[..], b"rld!");
  }

  #[test]
  fn separated_list() {
    let mut mem: [u8; 100] = [0; 100];
    let s = &mut mem[..];

    let mut empty_list = SeparatedList::new(", ".raw(), [].iter().map(|_: &u8| empty()));
    assert_eq!(empty_list.serialize(s), Ok((0, Serialized::Done)));

    let mut single_element_list = SeparatedList::new(", ".raw(), ["hello"].iter().map(|s| s.raw()));
    assert_eq!(single_element_list.serialize(s), Ok((5, Serialized::Done)));
    assert_eq!(from_utf8(&s[..5]).unwrap(), "hello");

    let mut three_element_list = SeparatedList::new(", ".raw(), ["hello", "world", "hello again"].iter().map(|s| s.raw()));
    assert_eq!(three_element_list.serialize(s), Ok((25, Serialized::Done)));
    assert_eq!(from_utf8(&s[..25]).unwrap(), "hello, world, hello again");

    let mut three_element_list_partial = SeparatedList::new(", ".raw(), ["hello", "world", "hello again"].iter().map(|s| s.raw()));
    assert_eq!(three_element_list_partial.serialize(&mut s[..6]), Ok((6, Serialized::Continue)));
    assert_eq!(from_utf8(&s[..6]).unwrap(), "hello,");
    assert_eq!(three_element_list_partial.serialize(&mut s[6..11]), Ok((5, Serialized::Continue)));
    assert_eq!(from_utf8(&s[..11]).unwrap(), "hello, worl");
    assert_eq!(three_element_list_partial.serialize(&mut s[11..14]), Ok((3, Serialized::Continue)));
    assert_eq!(from_utf8(&s[..14]).unwrap(), "hello, world, ");
    assert_eq!(three_element_list_partial.serialize(&mut s[14..20]), Ok((6, Serialized::Continue)));
    assert_eq!(from_utf8(&s[..20]).unwrap(), "hello, world, hello ");
    assert_eq!(three_element_list_partial.serialize(&mut s[20..]), Ok((5, Serialized::Done)));
    assert_eq!(from_utf8(&s[..26]).unwrap(), "hello, world, hello again\0");
  }
}
<commit_msg>add a combinator to enqueue things to serialize<commit_after>use gen::GenError;
use std::collections::VecDeque;

mod text;
mod binary;
pub use self::text::*;
pub use self::binary::*;

#[derive(Clone,Copy,Debug,PartialEq)]
pub enum Serialized {
  Done,
  Continue,
}

pub trait Serializer {
  fn serialize(&mut self, output: &mut [u8]) -> Result<(usize, Serialized), GenError>;

  #[inline(always)]
  fn then<T>(self, next: T) -> Then<Self, T>
    where
      Self: Sized,
      T: Serializer
  {
    Then::new(self, next)
  }
}

pub trait Reset {
  fn reset(&mut self) -> bool;
}

pub fn or<T,U>(t: Option<T>, u: U) -> Or<T, U>
  where
    T: Serializer,
    U: Serializer
{
  Or::new(t, u)
}

#[derive(Debug)]
pub struct Empty;

impl Serializer for Empty {
  #[inline(always)]
  fn serialize<'b, 'c>(&'b mut self, _output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    Ok((0, Serialized::Done))
  }
}

impl Reset for Empty {
  fn reset(&mut self) -> bool {
    true
  }
}

#[inline(always)]
pub fn empty() -> Empty {
  Empty
}

#[derive(Debug)]
pub struct Skip(usize);

impl Serializer for Skip {
  #[inline(always)]
  fn serialize<'b, 'c>(&'b mut self, output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    if output.len() < self.0 {
      Ok((0, Serialized::Continue))
    } else {
      Ok((self.0, Serialized::Done))
    }
  }
}

impl Reset for Skip {
  fn reset(&mut self) -> bool {
    true
  }
}

#[inline(always)]
pub fn skip(sz: usize) -> Skip {
  Skip(sz)
}

impl<S: ?Sized + Serializer> Serializer for Box<S> {
  #[inline(always)]
  fn serialize<'b, 'c>(&'b mut self, output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    (**self).serialize(output)
  }
}

pub struct Then<A, B> {
  a: Option<A>,
  b: B,
}

impl<A:Serializer, B:Serializer> Then<A, B> {
  #[inline(always)]
  pub fn new(a: A, b: B) -> Self {
    Then {
      a: Some(a),
      b,
    }
  }
}

impl<A:Serializer, B:Serializer> Serializer for Then<A,B> {
  #[inline(always)]
  fn serialize<'b, 'c>(&'b mut self, output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    let mut i = 0;
    if let Some(mut a) = self.a.take() {
      match a.serialize(output)? {
        (index, Serialized::Continue) => {
          self.a = Some(a);
          return Ok((index, Serialized::Continue))
        },
        (index, Serialized::Done) => {
          i = index;
        }
      }
    }

    let sl = &mut output[i..];
    self.b.serialize(sl).map(|(index, res)| (index+i, res))
  }
}

pub struct Or<A, B> {
  a: Option<A>,
  b: B,
}

impl<A:Serializer, B:Serializer> Or<A, B> {
  #[inline(always)]
  pub fn new(a: Option<A>, b: B) -> Self {
    Or {
      a,
      b,
    }
  }
}

impl<A:Serializer, B:Serializer> Serializer for Or<A,B> {
  #[inline(always)]
  fn serialize<'b, 'c>(&'b mut self, output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    match &mut self.a {
      Some(ref mut a) => a.serialize(output),
      None => self.b.serialize(output)
    }
  }
}

impl<A:Serializer+Reset, B:Serializer+Reset> Reset for Or<A, B> {
  fn reset(&mut self) -> bool {
    self.a.as_mut().map(|a| a.reset()).unwrap_or(self.b.reset())
  }
}

pub struct All<T,It> {
  current: Option<T>,
  it: It,
}

impl<T: Serializer, It: Iterator<Item=T>> All<T, It> {
  #[inline(always)]
  pub fn new<IntoIt: IntoIterator<Item=T, IntoIter=It>>(it: IntoIt) -> Self {
    All {
      current: None,
      it: it.into_iter(),
    }
  }
}

impl<T: Serializer, It: Iterator<Item=T>> Serializer for All<T, It> {
  fn serialize<'b, 'c>(&'b mut self, output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    let mut index = 0;

    loop {
      let mut current = match self.current.take() {
        Some(s) => s,
        None => match self.it.next() {
          Some(s) => s,
          None => return Ok((index, Serialized::Done)),
        }
      };

      let sl = &mut output[index..];
      match current.serialize(sl)? {
        (i, Serialized::Continue) => {
          self.current = Some(current);
          return Ok((index + i, Serialized::Continue));
        },
        (i, Serialized::Done) => {
          index += i;
        },
      }
    }
  }
}

#[inline(always)]
pub fn all<T: Serializer, It: Iterator<Item=T>, IntoIt: IntoIterator<Item=T, IntoIter=It>>(it: IntoIt) -> All<T, It> {
  All::new(it)
}

pub struct SeparatedList<T,U,It> {
  current: Option<T>,
  it: It,
  separator: U,
  serialize_element: bool,
}

impl<T: Serializer, U: Serializer+Reset, It: Iterator<Item=T>> SeparatedList<T, U, It> {
  #[inline(always)]
  pub fn new<IntoIt: IntoIterator<Item=T, IntoIter=It>>(separator: U, it: IntoIt) -> Self {
    let mut it = it.into_iter();
    SeparatedList {
      current: it.next(),
      it,
      separator,
      serialize_element: true,
    }
  }
}

impl<T: Serializer, U: Serializer+Reset, It: Iterator<Item=T>> Serializer for SeparatedList<T, U, It> {
  fn serialize<'b, 'c>(&'b mut self, output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    let mut index = 0;

    loop {
      let sl = &mut output[index..];

      if self.serialize_element {
        let mut current = match self.current.take() {
          Some(s) => s,
          None => return Ok((index, Serialized::Done)),
        };

        match current.serialize(sl)? {
          (i, Serialized::Continue) => {
            self.current = Some(current);
            return Ok((index + i, Serialized::Continue));
          },
          (i, Serialized::Done) => {
            index += i;
          },
        }

        self.current = self.it.next();
        if self.current.is_some() {
          self.serialize_element = false;
        }
      } else {
        // serialize separator
        match self.separator.serialize(sl)? {
          (i, Serialized::Continue) => {
            return Ok((index + i, Serialized::Continue));
          },
          (i, Serialized::Done) => {
            index += i;
            self.serialize_element = true;
            self.separator.reset();
          },

        }
      }
    }
  }
}

pub struct Stream<T> {
  queue: VecDeque<T>,
}

impl<T:Serializer> Stream<T> {
  #[inline(always)]
  pub fn new() -> Self {
    Stream {
      queue: VecDeque::new(),
    }
  }

  pub fn from_iter<It: Iterator<Item=T>>(it: It) -> Self {
    Stream {
      queue: it.collect(),
    }
  }

  pub fn push(&mut self, t: T) {
    self.queue.push_back(t);
  }
}

impl<T:Serializer> Serializer for Stream<T> {
  #[inline(always)]
  fn serialize<'b, 'c>(&'b mut self, output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    let mut index = 0;

    loop {
      match self.queue.front_mut() {
        None => return Ok((index, Serialized::Done)),
        Some(s) => match s.serialize(&mut output[index..])? {
          (i, Serialized::Continue) => return Ok((index+i, Serialized::Continue)),
          (i, Serialized::Done) => {
            index += i;
          }
        }
      }

      self.queue.pop_front();
    }
  }
}

impl Serializer for Fn(&mut [u8]) -> Result<(&mut [u8],usize),GenError> {
  fn serialize<'b, 'c>(&'b mut self, output: &'c mut [u8]) -> Result<(usize, Serialized), GenError> {
    match self(output) {
      Err(e) => Err(e),
      Ok((_, index)) => Ok((index, Serialized::Done)),
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use std::str::from_utf8;

  #[test]
  fn then_serializer() {
    let s1 = String::from("hello ");
    let sr1 = Slice::new(s1.as_str().as_bytes());

    let s2 = String::from("world!");
    let sr2 = s2.raw();//StrSerializer::new(s2.as_str());

    let mut sr = sr1.then(sr2);

    let mut mem: [u8; 4] = [0; 4];
    let s = &mut mem[..];

    assert_eq!(sr.serialize(s), Ok((4, Serialized::Continue)));
    assert_eq!(&s[..], b"hell");

    assert_eq!(sr.serialize(s), Ok((4, Serialized::Continue)));
    assert_eq!(&s[..], b"o wo");

    assert_eq!(sr.serialize(s), Ok((4, Serialized::Done)));
    assert_eq!(&s[..], b"rld!");
  }

  #[test]
  fn separated_list() {
    let mut mem: [u8; 100] = [0; 100];
    let s = &mut mem[..];

    let mut empty_list = SeparatedList::new(", ".raw(), [].iter().map(|_: &u8| empty()));
    assert_eq!(empty_list.serialize(s), Ok((0, Serialized::Done)));

    let mut single_element_list = SeparatedList::new(", ".raw(), ["hello"].iter().map(|s| s.raw()));
    assert_eq!(single_element_list.serialize(s), Ok((5, Serialized::Done)));
    assert_eq!(from_utf8(&s[..5]).unwrap(), "hello");

    let mut three_element_list = SeparatedList::new(", ".raw(), ["hello", "world", "hello again"].iter().map(|s| s.raw()));
    assert_eq!(three_element_list.serialize(s), Ok((25, Serialized::Done)));
    assert_eq!(from_utf8(&s[..25]).unwrap(), "hello, world, hello again");

    let mut three_element_list_partial = SeparatedList::new(", ".raw(), ["hello", "world", "hello again"].iter().map(|s| s.raw()));
    assert_eq!(three_element_list_partial.serialize(&mut s[..6]), Ok((6, Serialized::Continue)));
    assert_eq!(from_utf8(&s[..6]).unwrap(), "hello,");
    assert_eq!(three_element_list_partial.serialize(&mut s[6..11]), Ok((5, Serialized::Continue)));
    assert_eq!(from_utf8(&s[..11]).unwrap(), "hello, worl");
    assert_eq!(three_element_list_partial.serialize(&mut s[11..14]), Ok((3, Serialized::Continue)));
    assert_eq!(from_utf8(&s[..14]).unwrap(), "hello, world, ");
    assert_eq!(three_element_list_partial.serialize(&mut s[14..20]), Ok((6, Serialized::Continue)));
    assert_eq!(from_utf8(&s[..20]).unwrap(), "hello, world, hello ");
    assert_eq!(three_element_list_partial.serialize(&mut s[20..]), Ok((5, Serialized::Done)));
    assert_eq!(from_utf8(&s[..26]).unwrap(), "hello, world, hello again\0");
  }

  #[test]
  fn stream() {
    let mut mem: [u8; 100] = [0; 100];
    let s = &mut mem[..];

    let mut stream = Stream::from_iter(["hello ", "world! ", "hello again! "].iter().map(|s| s.raw()));
    assert_eq!(stream.serialize(&mut s[..7]), Ok((7, Serialized::Continue)));
    assert_eq!(from_utf8(&s[..7]).unwrap(), "hello w");

    stream.push("hi there!".raw());

    assert_eq!(stream.serialize(&mut s[7..20]), Ok((13, Serialized::Continue)));
    assert_eq!(from_utf8(&s[..20]).unwrap(), "hello world! hello a");

    assert_eq!(stream.serialize(&mut s[20..28]), Ok((8, Serialized::Continue)));
    assert_eq!(from_utf8(&s[..28]).unwrap(), "hello world! hello again! hi");

    assert_eq!(stream.serialize(&mut s[28..]), Ok((7, Serialized::Done)));
    assert_eq!(from_utf8(&s[..35]).unwrap(), "hello world! hello again! hi there!");
  }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs;
use std::path::Path;

use clap::ArgMatches;
use tempdir::TempDir;
use hyper::Client;
use util;
use extractor;
use downloader;
use profile;
use config::Config;

pub fn init() {
    let config = Config::new();
    if config.install_dir.exists() || config.shim_dir.exists() {
        println!("Already initalized. Reinitializing....");
    }
    fs::create_dir_all(&config.install_dir).expect("Could not create installation directory.");
    fs::create_dir_all(&config.shim_dir).expect("Could not create shims directory.");
    if !env::home_dir()
        .unwrap()
        .join("Documents")
        .join("WindowsPowerShell")
        .join("profile.ps1")
        .exists() {
        println!(r#"Please create profile.ps1 the following place:

$Env:USERPROFILE\Documents\WindowsPowerShell\profile.ps1

And write the following thing:

. $Env:USERPROFILE\.groonga\shims\bin\source-groonga.ps1
"#)
    }
}

pub fn install(m: &ArgMatches) {
    const BASE_URL: &'static str = "http://packages.groonga.org/windows/groonga";
    let config = Config::from_matches(m);
    println!("Value for architecture: {}",
             config.arch.clone().expect("unsupported platform"));
    println!("Obtaining Groonga version: {}",
             config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}-{}",
                              config.version.unwrap(),
                              config.arch.unwrap());
    let groonga_binary = format!("{}.zip", groonga_dir.clone());
    if config.versions_dir.join(groonga_dir.clone()).exists() {
        println!("Already installed. Ready to use it.");
        return ();
    }

    let download_dir = TempDir::new("grnenv-rs")
        .expect("Could not create temp dir.")
        .into_path();

    let client = Client::new();
    let filename = downloader::file_download(&client,
                                             &*format!("{}/{}", BASE_URL, groonga_binary),
                                             download_dir)
        .expect("Failed to download");
    extractor::extract_zip(&filename, &config.versions_dir);
}

pub fn switch(m: &ArgMatches) {
    let config = Config::from_matches(m);
    println!("Value for architecture: {}",
             config.arch.clone().expect("unsupported platform"));
    println!("Using Groonga version: {}", config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}-{}",
                              config.version.unwrap(),
                              config.arch.unwrap());
    match config.version {
        Some("system") => {
            profile::remove_grnenv_profile(&config.shim_dir).unwrap();
            return ();
        }
        Some(_) => {
            profile::create_profile_source(&config.shim_dir, &groonga_dir, &config.versions_dir)
                .expect("Could not create source-groonga.ps1")
        }
        None => unreachable!(),
    }
}

pub fn versions() {
    let groonga_versioned_dir = util::obtain_groonga_versioned_path();
    let paths = fs::read_dir(&Path::new(&groonga_versioned_dir)).unwrap();

    let names = paths.filter_map(|entry| {
            entry.ok().and_then(|e| {
                e.path()
                    .file_name()
                    .and_then(|n| n.to_str().map(|s| String::from(s)))
            })
        })
        .collect::<Vec<String>>();

    println!("Installed Groonga:");
    println!("\tsystem");
    for entry in names {
        println!("\t{}", entry);
    }
}

pub fn uninstall(m: &ArgMatches) {
    let config = Config::from_matches(m);
    let groonga_dir = format!("groonga-{}-{}",
                              config.version.unwrap(),
                              config.arch.unwrap());
    if config.versions_dir.join(groonga_dir.clone()).exists() {
        println!("Removing {}....", groonga_dir.clone());
        fs::remove_dir_all(&config.versions_dir.join(groonga_dir))
            .expect("Could not remove specified directory.");
    }
}
<commit_msg>Add error message and status<commit_after>use std::env;
use std::fs;
use std::path::Path;
use std::process;

use clap::ArgMatches;
use tempdir::TempDir;
use hyper::Client;
use util;
use extractor;
use downloader;
use profile;
use config::Config;

pub fn init() {
    let config = Config::new();
    if config.install_dir.exists() || config.shim_dir.exists() {
        println!("Already initalized. Reinitializing....");
    }
    fs::create_dir_all(&config.install_dir).expect("Could not create installation directory.");
    fs::create_dir_all(&config.shim_dir).expect("Could not create shims directory.");
    if !env::home_dir()
        .unwrap()
        .join("Documents")
        .join("WindowsPowerShell")
        .join("profile.ps1")
        .exists() {
        println!(r#"Please create profile.ps1 the following place:

$Env:USERPROFILE\Documents\WindowsPowerShell\profile.ps1

And write the following thing:

. $Env:USERPROFILE\.groonga\shims\bin\source-groonga.ps1
"#)
    }
}

pub fn install(m: &ArgMatches) {
    const BASE_URL: &'static str = "http://packages.groonga.org/windows/groonga";
    let config = Config::from_matches(m);
    println!("Value for architecture: {}",
             config.arch.clone().expect("unsupported platform"));
    println!("Obtaining Groonga version: {}",
             config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}-{}",
                              config.version.unwrap(),
                              config.arch.unwrap());
    let groonga_binary = format!("{}.zip", groonga_dir.clone());
    if config.versions_dir.join(groonga_dir.clone()).exists() {
        println!("Already installed. Ready to use it.");
        return ();
    }

    let download_dir = TempDir::new("grnenv-rs")
        .expect("Could not create temp dir.")
        .into_path();

    let client = Client::new();
    let filename = downloader::file_download(&client,
                                             &*format!("{}/{}", BASE_URL, groonga_binary),
                                             download_dir)
        .expect("Failed to download");
    extractor::extract_zip(&filename, &config.versions_dir);
}

pub fn switch(m: &ArgMatches) {
    let config = Config::from_matches(m);
    println!("Value for architecture: {}",
             config.arch.clone().expect("unsupported platform"));
    println!("Using Groonga version: {}", config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}-{}",
                              config.version.unwrap(),
                              config.arch.unwrap());
    match config.version {
        Some("system") => {
            profile::remove_grnenv_profile(&config.shim_dir).unwrap();
            return ();
        }
        Some(_) => {
            profile::create_profile_source(&config.shim_dir, &groonga_dir, &config.versions_dir)
                .expect("Could not create source-groonga.ps1")
        }
        None => unreachable!(),
    }
}

pub fn versions() {
    let groonga_versioned_dir = util::obtain_groonga_versioned_path();
    let paths = fs::read_dir(&Path::new(&groonga_versioned_dir)).unwrap();

    let names = paths.filter_map(|entry| {
            entry.ok().and_then(|e| {
                e.path()
                    .file_name()
                    .and_then(|n| n.to_str().map(|s| String::from(s)))
            })
        })
        .collect::<Vec<String>>();

    println!("Installed Groonga:");
    println!("\tsystem");
    for entry in names {
        println!("\t{}", entry);
    }
}

pub fn uninstall(m: &ArgMatches) {
    let config = Config::from_matches(m);
    let groonga_dir = format!("groonga-{}-{}",
                              config.version.unwrap(),
                              config.arch.unwrap());
    if config.versions_dir.join(groonga_dir.clone()).exists() {
        println!("Removing {}....", groonga_dir.clone());
        fs::remove_dir_all(&config.versions_dir.join(groonga_dir))
            .expect("Could not remove specified directory.");
    } else {
        println!("{} is not installed!", groonga_dir.clone());
        process::exit(1);
    }
}
<|endoftext|>


<commit_before>extern crate getopts;

use std::env;
use std::fs;
use std::io::Write;
use std::path::PathBuf;
use self::getopts::Options;
use command;
use git;

pub enum ParsedArgv {
    Help,
    Version,
    Parsed(command::Options, bool),
}

type ErrorMsg = String;

fn normalize_repo_format(mut s: String, dir: &PathBuf) -> Result<String, ErrorMsg> {
    if let Ok(url) = git::new(dir)?.remote_url(&s) {
        return Ok(url);
    }

    if !s.ends_with(".git") {
        s.push_str(".git");
    }

    if s.starts_with("git@") || s.starts_with("https://") || s.starts_with("http://") {
        return Ok(s);
    }

    match s.chars().filter(|c| *c == '/').count() {
        1 => Ok(format!("https://github.com/{}", s)),
        2 => Ok(format!("https://{}", s)),
        _ => Err(format!("Error: Invalid repository format '{}'. Format must be one of 'user/repo', 'service/user/repo' or remote name or Git URL.", s)),
    }
}

pub fn parse_options(argv: Vec<String>) -> Result<ParsedArgv, ErrorMsg> {
    let program = argv[0].clone();
    let mut opts = Options::new();

    opts.optopt("r", "repo", "Shorthand format (user/repo, service/user/repo) or remote name (e.g. origin) or Git URL you want to see", "REPO");
    opts.optopt("b", "branch", "Branch name of the repository", "BRANCH");
    opts.optopt("d", "dir", "Directory path to your repository", "PATH");
    opts.optflag("u", "url", "Output URL to STDOUT instead of opening in browser");
    opts.optflag("h", "help", "Print this help");
    opts.optflag("v", "version", "Show version");

    let matches = opts.parse(&argv[1..]).map_err(|f| format!("{}", f))?;

    if matches.opt_present("h") {
        let brief = format!("Usage: {} [Options] {{Args}}", program);
        errorln!("{}", opts.usage(&brief));
        return Ok(ParsedArgv::Help);
    }

    if matches.opt_present("v") {
        println!("{}", option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"));
        return Ok(ParsedArgv::Version);
    }

    let dir = match matches.opt_str("d") {
        Some(d) => fs::canonicalize(d).map_err(|e| format!("Error on --dir option: {}", e))?,
        // XXX: Should use 'git rev-parse --show-cdup' to get proper --git-dir
        None => env::current_dir().map_err(|e| format!("Error on --dir option: {}", e))?,
    };

    let (repo, branch) = match (matches.opt_str("r"), matches.opt_str("b")) {
        (Some(r), Some(b)) => (normalize_repo_format(r, &dir)?, b),
        (Some(r), None) => (normalize_repo_format(r, &dir)?, git::new(&dir)?.tracking_remote()?.1),
        (None, Some(b)) => (git::new(&dir)?.tracking_remote()?.0, b),
        (None, None) => git::new(&dir)?.tracking_remote()?,
    };

    let show_url = matches.opt_present("u");

    Ok(ParsedArgv::Parsed(command::Options {
        repo: repo,
        branch: branch,
        dir: dir,
        args: matches.free,
    }, show_url))
}

<commit_msg>change current working directory if --dir specified<commit_after>extern crate getopts;

use std::env;
use std::fs;
use std::io::Write;
use std::path::PathBuf;
use self::getopts::Options;
use command;
use git;

pub enum ParsedArgv {
    Help,
    Version,
    Parsed(command::Options, bool),
}

type ErrorMsg = String;

fn normalize_repo_format(mut s: String, dir: &PathBuf) -> Result<String, ErrorMsg> {
    if let Ok(url) = git::new(dir)?.remote_url(&s) {
        return Ok(url);
    }

    if !s.ends_with(".git") {
        s.push_str(".git");
    }

    if s.starts_with("git@") || s.starts_with("https://") || s.starts_with("http://") {
        return Ok(s);
    }

    match s.chars().filter(|c| *c == '/').count() {
        1 => Ok(format!("https://github.com/{}", s)),
        2 => Ok(format!("https://{}", s)),
        _ => Err(format!("Error: Invalid repository format '{}'. Format must be one of 'user/repo', 'service/user/repo' or remote name or Git URL.", s)),
    }
}

pub fn parse_options(argv: Vec<String>) -> Result<ParsedArgv, ErrorMsg> {
    let program = argv[0].clone();
    let mut opts = Options::new();

    opts.optopt("r", "repo", "Shorthand format (user/repo, service/user/repo) or remote name (e.g. origin) or Git URL you want to see", "REPO");
    opts.optopt("b", "branch", "Branch name of the repository", "BRANCH");
    opts.optopt("d", "dir", "Directory path to your repository", "PATH");
    opts.optflag("u", "url", "Output URL to STDOUT instead of opening in browser");
    opts.optflag("h", "help", "Print this help");
    opts.optflag("v", "version", "Show version");

    let matches = opts.parse(&argv[1..]).map_err(|f| format!("{}", f))?;

    if matches.opt_present("h") {
        let brief = format!("Usage: {} [Options] {{Args}}", program);
        errorln!("{}", opts.usage(&brief));
        return Ok(ParsedArgv::Help);
    }

    if matches.opt_present("v") {
        println!("{}", option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"));
        return Ok(ParsedArgv::Version);
    }

    let dir = match matches.opt_str("d") {
        Some(d) => {
            let c = fs::canonicalize(&d).map_err(|e| format!("Error on --dir option: {}", e))?;
            env::set_current_dir(&c).map_err(|e| format!("Error on setting current direcotry to {}: {}", d, e))?;
            c
        },
        None => env::current_dir().map_err(|e| format!("Error on --dir option: {}", e))?,
    };

    let (repo, branch) = match (matches.opt_str("r"), matches.opt_str("b")) {
        (Some(r), Some(b)) => (normalize_repo_format(r, &dir)?, b),
        (Some(r), None) => (normalize_repo_format(r, &dir)?, git::new(&dir)?.tracking_remote()?.1),
        (None, Some(b)) => (git::new(&dir)?.tracking_remote()?.0, b),
        (None, None) => git::new(&dir)?.tracking_remote()?,
    };

    let show_url = matches.opt_present("u");

    Ok(ParsedArgv::Parsed(command::Options {
        repo: repo,
        branch: branch,
        dir: dir,
        args: matches.free,
    }, show_url))
}

<|endoftext|>


<commit_before>use std::fmt;
use std::borrow::Cow;

use escape::Escaped;

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Attribute<'a> {
    pub name: Cow<'a, str>,
    pub value: Cow<'a, str>,
}

impl<'a> Attribute<'a> {
    pub fn new<N, V>(name: N, value: V) -> Attribute<'a>
        where N: Into<Cow<'a, str>>,
              V: Into<Cow<'a, str>>
    {
        Attribute {
            name: name.into(),
            value: value.into(),
        }
    }
}

impl<'a> fmt::Display for Attribute<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}=\"{}\"", self.name.as_ref(), Escaped(&self.value))
    }
}

#[derive(Clone, Debug)]
/// Prefer `attr_set!` macro over manual construction
pub struct AttributeSet<'a>(pub Cow<'a, [Attribute<'a>]>);

impl<'a> AttributeSet<'a> {
    pub fn get_attr<S>(&self, name: S) -> Option<&Attribute<'a>>
        where S: AsRef<str>
    {
        self.0.iter().find(|attr| attr.name == name.as_ref())
    }

    pub fn get_attr_mut<S>(&mut self, name: S) -> Option<&mut Attribute<'a>>
        where S: AsRef<str>
    {
        self.0.to_mut().iter_mut().find(|attr| attr.name == name.as_ref())
    }

    pub fn set_attr<N, V>(&mut self, name: N, value: V)
        where N: Into<Cow<'a, str>>,
              V: Into<Cow<'a, str>>
    {
        let (name, value) = (name.into(), value.into());
        let attrs = self.0.to_mut();

        if let Some(pos) = attrs.iter().position(|attr| attr.name == name) {
            attrs[pos].value = value;
        } else {
            attrs.push(Attribute::new(name, value));
        }
    }
}

impl<'a> fmt::Display for AttributeSet<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for attr in self.0.iter() {
            try!(write!(f, " {}", attr));
        }
        Ok(())
    }
}
<commit_msg>Use empty attribute syntax for empty attributes<commit_after>use std::fmt;
use std::borrow::Cow;

use escape::Escaped;

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Attribute<'a> {
    pub name: Cow<'a, str>,
    pub value: Cow<'a, str>,
}

impl<'a> Attribute<'a> {
    pub fn new<N, V>(name: N, value: V) -> Attribute<'a>
        where N: Into<Cow<'a, str>>,
              V: Into<Cow<'a, str>>
    {
        Attribute {
            name: name.into(),
            value: value.into(),
        }
    }
}

impl<'a> fmt::Display for Attribute<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.value == "" {
            write!(f, "{}", self.name)
        } else {
            write!(f, "{}=\"{}\"", self.name.as_ref(), Escaped(&self.value))
        }
    }
}

#[derive(Clone, Debug)]
/// Prefer `attr_set!` macro over manual construction
pub struct AttributeSet<'a>(pub Cow<'a, [Attribute<'a>]>);

impl<'a> AttributeSet<'a> {
    pub fn get_attr<S>(&self, name: S) -> Option<&Attribute<'a>>
        where S: AsRef<str>
    {
        self.0.iter().find(|attr| attr.name == name.as_ref())
    }

    pub fn get_attr_mut<S>(&mut self, name: S) -> Option<&mut Attribute<'a>>
        where S: AsRef<str>
    {
        self.0.to_mut().iter_mut().find(|attr| attr.name == name.as_ref())
    }

    pub fn set_attr<N, V>(&mut self, name: N, value: V)
        where N: Into<Cow<'a, str>>,
              V: Into<Cow<'a, str>>
    {
        let (name, value) = (name.into(), value.into());
        let attrs = self.0.to_mut();

        if let Some(pos) = attrs.iter().position(|attr| attr.name == name) {
            attrs[pos].value = value;
        } else {
            attrs.push(Attribute::new(name, value));
        }
    }
}

impl<'a> fmt::Display for AttributeSet<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for attr in self.0.iter() {
            try!(write!(f, " {}", attr));
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::sync::{Mutex, MutexGuard};
use std::hash::{Hash, SipHasher, Hasher};
use std::fmt;

use storage::{Key, RefKey, Value};
use storage::engine::{Engine, Modify};
use proto::mvccpb::{MetaLock, MetaLock_Type, MetaItem};
use util::codec::bytes;
use super::meta::Meta;
use super::codec;
use super::{Error, Result};

const SHARD_LOCK_SIZE: usize = 256;

fn shard_index(key: RefKey) -> usize {
    let mut s = SipHasher::new();
    key.hash(&mut s);
    (s.finish() as usize) % SHARD_LOCK_SIZE
}

#[derive(Debug)]
pub struct MvccStore {
    engine: Box<Engine>,
    shard_locks: Vec<Mutex<()>>,
}

impl MvccStore {
    pub fn new(engine: Box<Engine>) -> MvccStore {
        let mut locks = Vec::<_>::with_capacity(SHARD_LOCK_SIZE);
        for _ in 0..SHARD_LOCK_SIZE {
            locks.push(Mutex::new(()));
        }
        MvccStore {
            engine: engine,
            shard_locks: locks,
        }
    }

    pub fn start_row_transaction(&self, key: Key) -> Result<RowTxn> {
        let index = shard_index(&key);
        let guard = self.shard_locks[index].lock().unwrap();
        RowTxn::new(self.engine.as_ref(), key, guard)
    }

    pub fn get(&self, key: Key, ts: u64) -> Result<Option<Value>> {
        let txn = try!(self.start_row_transaction(key));
        txn.get(ts)
    }

    pub fn prewrite(&self, key: Key, args: Prewrite, primary: Key, ts: u64) -> Result<()> {
        let mut txn = try!(self.start_row_transaction(key));
        try!(txn.prewrite(args, primary, ts));
        try!(txn.write());
        Ok(())
    }

    pub fn commit(&self, key: Key, start_ts: u64, commit_ts: u64) -> Result<()> {
        let mut txn = try!(self.start_row_transaction(key));
        try!(txn.commit(start_ts, commit_ts));
        try!(txn.write());
        Ok(())
    }

    pub fn rollback(&self, key: Key, start_ts: u64) -> Result<()> {
        let mut txn = try!(self.start_row_transaction(key));
        try!(txn.rollback(start_ts));
        try!(txn.write());
        Ok(())
    }
}

#[allow(dead_code)]
pub struct RowTxn<'a> {
    engine: &'a Engine,
    row_key: Key,
    row_lock: MutexGuard<'a, ()>,
    meta_key: Key,
    meta: Meta,
    writes: Vec<Modify>,
}

impl<'a> fmt::Debug for RowTxn<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "txn: {:?} - {:?}", self.row_key, self.engine)
    }
}

impl<'a> RowTxn<'a> {
    fn new(engine: &'a Engine, row_key: Key, lock: MutexGuard<'a, ()>) -> Result<RowTxn<'a>> {
        let meta_key = bytes::encode_bytes(&row_key);
        let meta = match try!(engine.get(&meta_key)) {
            Some(x) => try!(Meta::parse(&x)),
            None => Meta::new(),
        };
        Ok(RowTxn {
            engine: engine,
            row_key: row_key,
            row_lock: lock,
            meta_key: meta_key,
            meta: meta,
            writes: vec![],
        })
    }

    pub fn write(&mut self) -> Result<()> {
        let batch = self.writes.drain(..).collect();
        try!(self.engine.write(batch));
        Ok(())
    }

    pub fn get(&self, ts: u64) -> Result<Option<Value>> {
        if let Some(lock) = self.meta.get_lock() {
            if lock.get_start_ts() <= ts {
                return Err(Error::KeyIsLocked {
                    primary: lock.get_primary_key().to_vec(),
                    ts: lock.get_start_ts(),
                });
            }
        }
        match self.meta.iter_items().find(|x| x.get_commit_ts() <= ts) {
            Some(x) => {
                let data_key = codec::encode_key(&self.row_key, x.get_start_ts());
                Ok(try!(self.engine.get(&data_key)))
            }
            None => Ok(None),
        }
    }

    pub fn prewrite(&mut self, args: Prewrite, primary: Key, ts: u64) -> Result<()> {
        if let Some(lock) = self.meta.get_lock() {
            return Err(Error::KeyIsLocked {
                primary: lock.get_primary_key().to_vec(),
                ts: lock.get_start_ts(),
            });
        }
        if self.meta.iter_items().any(|x| x.get_commit_ts() >= ts) {
            return Err(Error::WriteConflict);
        }

        let mut lock = MetaLock::new();
        lock.set_field_type(match args {
            Prewrite::Lock => MetaLock_Type::ReadOnly,
            _ => MetaLock_Type::ReadWrite,
        });
        lock.set_primary_key(primary);
        lock.set_start_ts(ts);
        self.meta.set_lock(lock);
        let modify = Modify::Put((self.meta_key.clone(), self.meta_bytes()));
        self.writes.push(modify);

        if let Prewrite::Put(value) = args {
            let value_key = codec::encode_key(&self.row_key, ts);
            self.writes.push(Modify::Put((value_key, value)));
        }
        Ok(())
    }

    pub fn commit(&mut self, start_ts: u64, commit_ts: u64) -> Result<()> {
        let lock_type = match self.meta.get_lock() {
            Some(lock) if lock.get_start_ts() == start_ts => lock.get_field_type(),
            _ => return Err(Error::TxnAbortedWhileWorking),
        };
        if lock_type == MetaLock_Type::ReadWrite {
            let mut item = MetaItem::new();
            item.set_start_ts(start_ts);
            item.set_commit_ts(commit_ts);
            self.meta.push_item(item);
        }
        self.meta.clear_lock();
        let modify = Modify::Put((self.meta_key.clone(), self.meta_bytes()));
        self.writes.push(modify);
        Ok(())
    }

    #[allow(dead_code)]
    pub fn rollback(&mut self, start_ts: u64) -> Result<()> {
        match self.meta.get_lock() {
            Some(lock) if lock.get_start_ts() == start_ts => {
                if lock.get_field_type() == MetaLock_Type::ReadWrite {
                    let value_key = codec::encode_key(&self.row_key, lock.get_start_ts());
                    self.writes.push(Modify::Delete(value_key));
                }
            }
            _ => return Err(Error::TxnAbortedWhileWorking),
        }
        self.meta.clear_lock();
        let modify = Modify::Put((self.meta_key.clone(), self.meta_bytes()));
        self.writes.push(modify);
        Ok(())
    }

    fn meta_bytes(&self) -> Value {
        let mut data = vec![];
        self.meta.write_to(&mut data);
        data
    }
}

#[derive(Debug)]
pub enum Prewrite {
    Put(Value),
    Delete,
    Lock,
}

#[cfg(test)]
mod tests {
    use super::{MvccStore, Prewrite};
    use storage::engine::{self, Engine, Dsn};

    #[test]
    fn test_mvcc_store_read() {
        let engine = engine::new_engine(Dsn::Memory).unwrap();
        let store = MvccStore::new(engine);

        must_get_none(&store, b"x", 1);

        must_prewrite_put(&store, b"x", b"x5", b"x", 5);
        must_get_none(&store, b"x", 3);
        must_get_err(&store, b"x", 7);

        must_commit(&store, b"x", 5, 10);
        must_get_none(&store, b"x", 3);
        must_get_none(&store, b"x", 7);
        must_get(&store, b"x", 13, b"x5");

        must_prewrite_delete(&store, b"x", b"x", 15);
        must_commit(&store, b"x", 15, 20);
        must_get_none(&store, b"x", 3);
        must_get_none(&store, b"x", 7);
        must_get(&store, b"x", 13, b"x5");
        must_get(&store, b"x", 17, b"x5");
        must_get_none(&store, b"x", 23);
    }

    #[test]
    fn test_mvcc_store_write() {
        let engine = engine::new_engine(Dsn::Memory).unwrap();
        let store = MvccStore::new(engine);

        must_prewrite_put(&store, b"x", b"x5", b"x", 5);
        must_prewrite_lock_err(&store, b"x", b"x", 6);
        must_commit(&store, b"x", 5, 10);
        must_prewrite_lock_err(&store, b"x", b"x", 6);
        must_prewrite_lock(&store, b"x", b"x", 12);
    }

    #[test]
    fn test_mvcc_store_rollback() {
        let engine = engine::new_engine(Dsn::Memory).unwrap();
        let store = MvccStore::new(engine);

        must_prewrite_put(&store, b"x", b"x5", b"x", 5);
        must_rollback(&store, b"x", 5);
        must_prewrite_lock(&store, b"x", b"x", 6);
    }

    fn must_get(store: &MvccStore, key: &[u8], ts: u64, expect: &[u8]) {
        assert_eq!(store.get(key.to_vec(), ts).unwrap().unwrap(), expect);
    }

    fn must_get_none(store: &MvccStore, key: &[u8], ts: u64) {
        assert!(store.get(key.to_vec(), ts).unwrap().is_none());
    }

    fn must_get_err(store: &MvccStore, key: &[u8], ts: u64) {
        assert!(store.get(key.to_vec(), ts).is_err());
    }

    fn must_prewrite_put(store: &MvccStore, key: &[u8], value: &[u8], pk: &[u8], ts: u64) {
        store.prewrite(key.to_vec(), Prewrite::Put(value.to_vec()), pk.to_vec(), ts).unwrap();
    }

    fn must_prewrite_delete(store: &MvccStore, key: &[u8], pk: &[u8], ts: u64) {
        store.prewrite(key.to_vec(), Prewrite::Delete, pk.to_vec(), ts).unwrap();
    }

    fn must_prewrite_lock(store: &MvccStore, key: &[u8], pk: &[u8], ts: u64) {
        store.prewrite(key.to_vec(), Prewrite::Lock, pk.to_vec(), ts).unwrap();
    }

    fn must_prewrite_lock_err(store: &MvccStore, key: &[u8], pk: &[u8], ts: u64) {
        assert!(store.prewrite(key.to_vec(), Prewrite::Lock, pk.to_vec(), ts).is_err());
    }

    fn must_commit(store: &MvccStore, key: &[u8], start_ts: u64, commit_ts: u64) {
        store.commit(key.to_vec(), start_ts, commit_ts).unwrap();
    }

    fn must_rollback(store: &MvccStore, key: &[u8], start_ts: u64) {
        store.rollback(key.to_vec(), start_ts).unwrap();
    }
}
<commit_msg>storage/mvcc: update prewrite logic<commit_after>use std::sync::{Mutex, MutexGuard};
use std::hash::{Hash, SipHasher, Hasher};
use std::fmt;

use storage::{Key, RefKey, Value};
use storage::engine::{Engine, Modify};
use proto::mvccpb::{MetaLock, MetaLock_Type, MetaItem};
use util::codec::bytes;
use super::meta::Meta;
use super::codec;
use super::{Error, Result};

const SHARD_LOCK_SIZE: usize = 256;

fn shard_index(key: RefKey) -> usize {
    let mut s = SipHasher::new();
    key.hash(&mut s);
    (s.finish() as usize) % SHARD_LOCK_SIZE
}

#[derive(Debug)]
pub struct MvccStore {
    engine: Box<Engine>,
    shard_locks: Vec<Mutex<()>>,
}

impl MvccStore {
    pub fn new(engine: Box<Engine>) -> MvccStore {
        let mut locks = Vec::<_>::with_capacity(SHARD_LOCK_SIZE);
        for _ in 0..SHARD_LOCK_SIZE {
            locks.push(Mutex::new(()));
        }
        MvccStore {
            engine: engine,
            shard_locks: locks,
        }
    }

    pub fn start_row_transaction(&self, key: Key) -> Result<RowTxn> {
        let index = shard_index(&key);
        let guard = self.shard_locks[index].lock().unwrap();
        RowTxn::new(self.engine.as_ref(), key, guard)
    }

    pub fn get(&self, key: Key, ts: u64) -> Result<Option<Value>> {
        let txn = try!(self.start_row_transaction(key));
        txn.get(ts)
    }

    pub fn prewrite(&self, key: Key, args: Prewrite, primary: Key, ts: u64) -> Result<()> {
        let mut txn = try!(self.start_row_transaction(key));
        try!(txn.prewrite(args, primary, ts));
        try!(txn.write());
        Ok(())
    }

    pub fn commit(&self, key: Key, start_ts: u64, commit_ts: u64) -> Result<()> {
        let mut txn = try!(self.start_row_transaction(key));
        try!(txn.commit(start_ts, commit_ts));
        try!(txn.write());
        Ok(())
    }

    pub fn rollback(&self, key: Key, start_ts: u64) -> Result<()> {
        let mut txn = try!(self.start_row_transaction(key));
        try!(txn.rollback(start_ts));
        try!(txn.write());
        Ok(())
    }
}

#[allow(dead_code)]
pub struct RowTxn<'a> {
    engine: &'a Engine,
    row_key: Key,
    row_lock: MutexGuard<'a, ()>,
    meta_key: Key,
    meta: Meta,
    writes: Vec<Modify>,
}

impl<'a> fmt::Debug for RowTxn<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "txn: {:?} - {:?}", self.row_key, self.engine)
    }
}

impl<'a> RowTxn<'a> {
    fn new(engine: &'a Engine, row_key: Key, lock: MutexGuard<'a, ()>) -> Result<RowTxn<'a>> {
        let meta_key = bytes::encode_bytes(&row_key);
        let meta = match try!(engine.get(&meta_key)) {
            Some(x) => try!(Meta::parse(&x)),
            None => Meta::new(),
        };
        Ok(RowTxn {
            engine: engine,
            row_key: row_key,
            row_lock: lock,
            meta_key: meta_key,
            meta: meta,
            writes: vec![],
        })
    }

    pub fn write(&mut self) -> Result<()> {
        let batch = self.writes.drain(..).collect();
        try!(self.engine.write(batch));
        Ok(())
    }

    pub fn get(&self, ts: u64) -> Result<Option<Value>> {
        if let Some(lock) = self.meta.get_lock() {
            if lock.get_start_ts() <= ts {
                return Err(Error::KeyIsLocked {
                    primary: lock.get_primary_key().to_vec(),
                    ts: lock.get_start_ts(),
                });
            }
        }
        match self.meta.iter_items().find(|x| x.get_commit_ts() <= ts) {
            Some(x) => {
                let data_key = codec::encode_key(&self.row_key, x.get_start_ts());
                Ok(try!(self.engine.get(&data_key)))
            }
            None => Ok(None),
        }
    }

    pub fn prewrite(&mut self, args: Prewrite, primary: Key, ts: u64) -> Result<()> {
        if let Some(lock) = self.meta.get_lock() {
            return Err(Error::KeyIsLocked {
                primary: lock.get_primary_key().to_vec(),
                ts: lock.get_start_ts(),
            });
        }
        match self.meta.iter_items().nth(0) {
            Some(item) if item.get_commit_ts() >= ts => return Err(Error::WriteConflict),
            _ => {}
        }

        let mut lock = MetaLock::new();
        lock.set_field_type(match args {
            Prewrite::Lock => MetaLock_Type::ReadOnly,
            _ => MetaLock_Type::ReadWrite,
        });
        lock.set_primary_key(primary);
        lock.set_start_ts(ts);
        self.meta.set_lock(lock);
        let modify = Modify::Put((self.meta_key.clone(), self.meta_bytes()));
        self.writes.push(modify);

        if let Prewrite::Put(value) = args {
            let value_key = codec::encode_key(&self.row_key, ts);
            self.writes.push(Modify::Put((value_key, value)));
        }
        Ok(())
    }

    pub fn commit(&mut self, start_ts: u64, commit_ts: u64) -> Result<()> {
        let lock_type = match self.meta.get_lock() {
            Some(lock) if lock.get_start_ts() == start_ts => lock.get_field_type(),
            _ => return Err(Error::TxnAbortedWhileWorking),
        };
        if lock_type == MetaLock_Type::ReadWrite {
            let mut item = MetaItem::new();
            item.set_start_ts(start_ts);
            item.set_commit_ts(commit_ts);
            self.meta.push_item(item);
        }
        self.meta.clear_lock();
        let modify = Modify::Put((self.meta_key.clone(), self.meta_bytes()));
        self.writes.push(modify);
        Ok(())
    }

    #[allow(dead_code)]
    pub fn rollback(&mut self, start_ts: u64) -> Result<()> {
        match self.meta.get_lock() {
            Some(lock) if lock.get_start_ts() == start_ts => {
                if lock.get_field_type() == MetaLock_Type::ReadWrite {
                    let value_key = codec::encode_key(&self.row_key, lock.get_start_ts());
                    self.writes.push(Modify::Delete(value_key));
                }
            }
            _ => return Err(Error::TxnAbortedWhileWorking),
        }
        self.meta.clear_lock();
        let modify = Modify::Put((self.meta_key.clone(), self.meta_bytes()));
        self.writes.push(modify);
        Ok(())
    }

    fn meta_bytes(&self) -> Value {
        let mut data = vec![];
        self.meta.write_to(&mut data);
        data
    }
}

#[derive(Debug)]
pub enum Prewrite {
    Put(Value),
    Delete,
    Lock,
}

#[cfg(test)]
mod tests {
    use super::{MvccStore, Prewrite};
    use storage::engine::{self, Engine, Dsn};

    #[test]
    fn test_mvcc_store_read() {
        let engine = engine::new_engine(Dsn::Memory).unwrap();
        let store = MvccStore::new(engine);

        must_get_none(&store, b"x", 1);

        must_prewrite_put(&store, b"x", b"x5", b"x", 5);
        must_get_none(&store, b"x", 3);
        must_get_err(&store, b"x", 7);

        must_commit(&store, b"x", 5, 10);
        must_get_none(&store, b"x", 3);
        must_get_none(&store, b"x", 7);
        must_get(&store, b"x", 13, b"x5");

        must_prewrite_delete(&store, b"x", b"x", 15);
        must_commit(&store, b"x", 15, 20);
        must_get_none(&store, b"x", 3);
        must_get_none(&store, b"x", 7);
        must_get(&store, b"x", 13, b"x5");
        must_get(&store, b"x", 17, b"x5");
        must_get_none(&store, b"x", 23);
    }

    #[test]
    fn test_mvcc_store_write() {
        let engine = engine::new_engine(Dsn::Memory).unwrap();
        let store = MvccStore::new(engine);

        must_prewrite_put(&store, b"x", b"x5", b"x", 5);
        must_prewrite_lock_err(&store, b"x", b"x", 6);
        must_commit(&store, b"x", 5, 10);
        must_prewrite_lock_err(&store, b"x", b"x", 6);
        must_prewrite_lock(&store, b"x", b"x", 12);
    }

    #[test]
    fn test_mvcc_store_rollback() {
        let engine = engine::new_engine(Dsn::Memory).unwrap();
        let store = MvccStore::new(engine);

        must_prewrite_put(&store, b"x", b"x5", b"x", 5);
        must_rollback(&store, b"x", 5);
        must_prewrite_lock(&store, b"x", b"x", 6);
    }

    fn must_get(store: &MvccStore, key: &[u8], ts: u64, expect: &[u8]) {
        assert_eq!(store.get(key.to_vec(), ts).unwrap().unwrap(), expect);
    }

    fn must_get_none(store: &MvccStore, key: &[u8], ts: u64) {
        assert!(store.get(key.to_vec(), ts).unwrap().is_none());
    }

    fn must_get_err(store: &MvccStore, key: &[u8], ts: u64) {
        assert!(store.get(key.to_vec(), ts).is_err());
    }

    fn must_prewrite_put(store: &MvccStore, key: &[u8], value: &[u8], pk: &[u8], ts: u64) {
        store.prewrite(key.to_vec(), Prewrite::Put(value.to_vec()), pk.to_vec(), ts).unwrap();
    }

    fn must_prewrite_delete(store: &MvccStore, key: &[u8], pk: &[u8], ts: u64) {
        store.prewrite(key.to_vec(), Prewrite::Delete, pk.to_vec(), ts).unwrap();
    }

    fn must_prewrite_lock(store: &MvccStore, key: &[u8], pk: &[u8], ts: u64) {
        store.prewrite(key.to_vec(), Prewrite::Lock, pk.to_vec(), ts).unwrap();
    }

    fn must_prewrite_lock_err(store: &MvccStore, key: &[u8], pk: &[u8], ts: u64) {
        assert!(store.prewrite(key.to_vec(), Prewrite::Lock, pk.to_vec(), ts).is_err());
    }

    fn must_commit(store: &MvccStore, key: &[u8], start_ts: u64, commit_ts: u64) {
        store.commit(key.to_vec(), start_ts, commit_ts).unwrap();
    }

    fn must_rollback(store: &MvccStore, key: &[u8], start_ts: u64) {
        store.rollback(key.to_vec(), start_ts).unwrap();
    }
}
<|endoftext|>


<commit_before>//! Diagnostic reporting support for the codespan crate

use codespan::ByteSpan;
#[cfg(feature = "serialization")]
use serde::{Deserialize, Serialize};

use crate::Severity;

/// A label describing an underlined region of code associated with a diagnostic.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "memory_usage", derive(heapsize_derive::HeapSizeOf))]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub struct Label {
    /// The span we are going to include in the final snippet.
    pub span: ByteSpan,
    /// A message to provide some additional information for the underlined code.
    pub message: String,
}

impl Label {
    pub fn new(span: ByteSpan, message: impl Into<String>) -> Label {
        Label {
            span,
            message: message.into(),
        }
    }
}

/// Represents a diagnostic message and associated child messages.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "memory_usage", derive(heapsize_derive::HeapSizeOf))]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub struct Diagnostic {
    /// The overall severity of the diagnostic
    pub severity: Severity,
    /// An optional code that identifies this diagnostic.
    pub code: Option<String>,
    /// The main message associated with this diagnostic.
    pub message: String,
    /// A label that marks the primary cause of this diagnostic.
    pub primary_label: Label,
    /// Secondary labels that provide additional context for the diagnostic.
    pub secondary_labels: Vec<Label>,
}

impl Diagnostic {
    pub fn new(severity: Severity, message: impl Into<String>, primary_label: Label) -> Diagnostic {
        Diagnostic {
            severity,
            code: None,
            message: message.into(),
            primary_label,
            secondary_labels: Vec::new(),
        }
    }

    pub fn new_bug(message: impl Into<String>, primary_label: Label) -> Diagnostic {
        Diagnostic::new(Severity::Bug, message, primary_label)
    }

    pub fn new_error(message: impl Into<String>, primary_label: Label) -> Diagnostic {
        Diagnostic::new(Severity::Error, message, primary_label)
    }

    pub fn new_warning(message: impl Into<String>, primary_label: Label) -> Diagnostic {
        Diagnostic::new(Severity::Warning, message, primary_label)
    }

    pub fn new_note(message: impl Into<String>, primary_label: Label) -> Diagnostic {
        Diagnostic::new(Severity::Note, message, primary_label)
    }

    pub fn new_help(message: impl Into<String>, primary_label: Label) -> Diagnostic {
        Diagnostic::new(Severity::Help, message, primary_label)
    }

    pub fn with_code(mut self, code: impl Into<String>) -> Diagnostic {
        self.code = Some(code.into());
        self
    }

    pub fn with_secondary_labels(mut self, labels: impl IntoIterator<Item = Label>) -> Diagnostic {
        self.secondary_labels.extend(labels);
        self
    }
}
<commit_msg>Improve doc comments<commit_after>//! Diagnostic reporting support for the codespan crate

use codespan::ByteSpan;
#[cfg(feature = "serialization")]
use serde::{Deserialize, Serialize};

use crate::Severity;

/// A label describing an underlined region of code associated with a diagnostic.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "memory_usage", derive(heapsize_derive::HeapSizeOf))]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub struct Label {
    /// The span we are going to include in the final snippet.
    pub span: ByteSpan,
    /// A message to provide some additional information for the underlined code.
    pub message: String,
}

impl Label {
    pub fn new(span: ByteSpan, message: impl Into<String>) -> Label {
        Label {
            span,
            message: message.into(),
        }
    }
}

/// Represents a diagnostic message that can provide information like errors and
/// warnings to the user.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "memory_usage", derive(heapsize_derive::HeapSizeOf))]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub struct Diagnostic {
    /// The overall severity of the diagnostic
    pub severity: Severity,
    /// An optional code that identifies this diagnostic.
    pub code: Option<String>,
    /// The main message associated with this diagnostic.
    pub message: String,
    /// A label that describes the primary cause of this diagnostic.
    pub primary_label: Label,
    /// Secondary labels that provide additional context for the diagnostic.
    pub secondary_labels: Vec<Label>,
}

impl Diagnostic {
    pub fn new(severity: Severity, message: impl Into<String>, primary_label: Label) -> Diagnostic {
        Diagnostic {
            severity,
            code: None,
            message: message.into(),
            primary_label,
            secondary_labels: Vec::new(),
        }
    }

    pub fn new_bug(message: impl Into<String>, primary_label: Label) -> Diagnostic {
        Diagnostic::new(Severity::Bug, message, primary_label)
    }

    pub fn new_error(message: impl Into<String>, primary_label: Label) -> Diagnostic {
        Diagnostic::new(Severity::Error, message, primary_label)
    }

    pub fn new_warning(message: impl Into<String>, primary_label: Label) -> Diagnostic {
        Diagnostic::new(Severity::Warning, message, primary_label)
    }

    pub fn new_note(message: impl Into<String>, primary_label: Label) -> Diagnostic {
        Diagnostic::new(Severity::Note, message, primary_label)
    }

    pub fn new_help(message: impl Into<String>, primary_label: Label) -> Diagnostic {
        Diagnostic::new(Severity::Help, message, primary_label)
    }

    pub fn with_code(mut self, code: impl Into<String>) -> Diagnostic {
        self.code = Some(code.into());
        self
    }

    pub fn with_secondary_labels(mut self, labels: impl IntoIterator<Item = Label>) -> Diagnostic {
        self.secondary_labels.extend(labels);
        self
    }
}
<|endoftext|>


<commit_before>extern crate hyper;

use std::sync::mpsc::{Receiver, channel, Sender};
use std::thread;
use args::Config;
use run_info::RunInfo;
use misc::split_number;
use tokio_core::reactor::Core;
use chrono::{Duration, Local};
use hyper::{Client, Url};
use std::str::FromStr;
use hyper::client::HttpConnector;

use futures::{Future, stream};
use futures::future::{ok, loop_fn, Loop};
use futures::Stream;
use futures_utils::stopwatch;
use request_result::RequestResult;
use errors::*;

/// Delegates and manages all the work.
pub struct Boss {
    /// Number of requests successfully completed
    pub requests_completed: usize,
    /// Number of active connections
    pub connections: usize,
    num_threads: usize,
}

impl Boss {
    pub fn new(num_threads: usize) -> Self {
        Boss {
            requests_completed: 0,
            connections: 0,
            num_threads: num_threads,
        }
    }

    pub fn start_workforce(&self, config: &Config) -> Result<RunInfo> {
        let (tx, rx) = channel();
        let desired_connections_per_worker_iter = split_number(config.num_connections,
                                                               self.num_threads);
        // start num_threads workers
        for desired_connections_per_worker in desired_connections_per_worker_iter {
            let tx = tx.clone();
            let url = config.url.clone();
            let timeout = config.timeout.to_std()?;
            let hyper_url = Url::from_str(&url)?;
            thread::spawn(move || {
                // TODO: how to use error_chain on tokio-core?
                let mut core = Core::new().expect("Failed to create Tokio core");
                let hyper_client = hyper::Client::configure()
                    .keep_alive_timeout(Some(timeout))
                    .build(&core.handle());

                let iterator = (0..desired_connections_per_worker).map(|_| {
                    let tx = tx.clone();

                    create_looping_worker(hyper_url.clone(), &hyper_client)
                        .for_each(move |req| {
                            tx.send(req);
                            ok(())
                        })
                });
                // create stream of requests
                let request_stream = stream::futures_unordered(iterator);
                // TODO: how to use error_chain with tokio?
                let _ = core.run(request_stream.into_future());
            });
        }

        Ok(self.collect_workers(rx, config.duration))
    }

    /// Collects information from all workers
    fn collect_workers(&self, rx: Receiver<RequestResult>, run_duration: Duration) -> RunInfo {
        let start_time = Local::now();
        let wanted_end_time = start_time + run_duration;
        rx.iter()
            .take_while(|_| Local::now() < wanted_end_time)
            .fold(RunInfo::new(run_duration), |mut runinfo_acc, request_result| {
                runinfo_acc.add_request(&request_result);
                runinfo_acc
            })
    }
}

fn create_looping_worker<'a>(url: Url,
                             hyper_client: &'a Client<HttpConnector>
                             )
                             -> impl Stream<Item = RequestResult, Error = ()> + 'a {
    stream::unfold(0u32, move |state| {
        let res = send_request(url.clone(), hyper_client);

        let fut = res.and_then(move |req| ok::<_, _>((req, state)));
        Some(fut)
    })
}

fn send_request<C>(url: Url,
                   hyper_client: &Client<C>)
                   -> impl Future<Item = RequestResult, Error = ()>
    where C: hyper::client::Connect
{
    stopwatch(hyper_client.get(url))
        .and_then(|(_, latency)| {
            let request_result = RequestResult::Success { latency: latency };
            Ok(request_result)
        })
        .or_else(|_| ok(RequestResult::Failure))
}
<commit_msg>use future mpsc<commit_after>extern crate hyper;

use futures::sync::mpsc::{Receiver, channel, unbounded, Sender, UnboundedReceiver};
use std::thread;
use args::Config;
use run_info::RunInfo;
use misc::split_number;
use tokio_core::reactor::Core;
use chrono::{Duration, Local};
use hyper::{Client, Url};
use std::str::FromStr;
use hyper::client::HttpConnector;

use futures::{Future, stream};
use futures::future::{ok, loop_fn, Loop};
use futures::Stream;
use futures_utils::stopwatch;
use request_result::RequestResult;
use errors::*;

/// Delegates and manages all the work.
pub struct Boss {
    /// Number of requests successfully completed
    pub requests_completed: usize,
    /// Number of active connections
    pub connections: usize,
    num_threads: usize,
}

impl Boss {
    pub fn new(num_threads: usize) -> Self {
        Boss {
            requests_completed: 0,
            connections: 0,
            num_threads: num_threads,
        }
    }

    pub fn start_workforce(&self, config: &Config) -> Result<RunInfo> {
        let (tx, rx) = unbounded();
        let desired_connections_per_worker_iter = split_number(config.num_connections,
                                                               self.num_threads);
        // start num_threads workers
        for desired_connections_per_worker in desired_connections_per_worker_iter {
            let tx = tx.clone();
            let url = config.url.clone();
            let timeout = config.timeout.to_std()?;
            let hyper_url = Url::from_str(&url)?;
            thread::spawn(move || {
                // TODO: how to use error_chain on tokio-core?
                let mut core = Core::new().expect("Failed to create Tokio core");
                let hyper_client = hyper::Client::configure()
                    .keep_alive_timeout(Some(timeout))
                    .build(&core.handle());

                let iterator = (0..desired_connections_per_worker).map(|_| {
                    let tx = tx.clone();

                    create_looping_worker(hyper_url.clone(), &hyper_client)
                        .for_each(move |req| {
                            tx.send(req);
                            ok(())
                        })
                });
                // create stream of requests
                let request_stream = stream::futures_unordered(iterator);
                // TODO: how to use error_chain with tokio?
                let _ = core.run(request_stream.into_future());
            });
        }

        Ok(self.collect_workers(rx, config.duration))
    }

    /// Collects information from all workers
    fn collect_workers(&self, rx: UnboundedReceiver<RequestResult>, run_duration: Duration) -> RunInfo {
        let start_time = Local::now();
        let wanted_end_time = start_time + run_duration;
        rx
            .take_while(|_| ok(Local::now() < wanted_end_time))
            .fold(RunInfo::new(run_duration), |mut runinfo_acc, request_result| {
                runinfo_acc.add_request(&request_result);
                ok(runinfo_acc)
            }).wait().unwrap()
    }
}

fn create_looping_worker<'a>(url: Url,
                             hyper_client: &'a Client<HttpConnector>
                             )
                             -> impl Stream<Item = RequestResult, Error = ()> + 'a {
    stream::unfold(0u32, move |state| {
        let res = send_request(url.clone(), hyper_client);

        let fut = res.and_then(move |req| ok::<_, _>((req, state)));
        Some(fut)
    })
}

fn send_request<C>(url: Url,
                   hyper_client: &Client<C>)
                   -> impl Future<Item = RequestResult, Error = ()>
    where C: hyper::client::Connect
{
    stopwatch(hyper_client.get(url))
        .and_then(|(_, latency)| {
            let request_result = RequestResult::Success { latency: latency };
            Ok(request_result)
        })
        .or_else(|_| ok(RequestResult::Failure))
}
<|endoftext|>


<commit_before>use primitives::{Consumed, Parser, ParseError, ParseResult, Error, State, Stream};
use combinator::{Expected, skip_many, SkipMany, ParserExt, With};
use std::borrow::IntoCow;

macro_rules! impl_char_parser {
    ($name: ident ($($ty_var: ident),*), $inner_type: ty) => {
    #[derive(Clone)]
    pub struct $name<I $(,$ty_var)*>($inner_type)
        where I: Stream<Item=char> $(, $ty_var : Parser<Input=I>)*;
    impl <I $(,$ty_var)*> Parser for $name<I $(,$ty_var)*>
        where I: Stream<Item=char> $(, $ty_var : Parser<Input=I>)* {
        type Input = I;
        type Output = <$inner_type as Parser>::Output;
        fn parse_state(&mut self, input: State<<Self as Parser>::Input>) -> ParseResult<<Self as Parser>::Output, <Self as Parser>::Input> {
            self.0.parse_state(input)
        }
    }
}
}

///Parses any character
pub fn any_char<I>(input: State<I>) -> ParseResult<char, I>
    where I: Stream<Item=char> {
    input.uncons_char()
}

#[derive(Clone)]
pub struct Satisfy<I, Pred> { pred: Pred }

impl <I, Pred> Parser for Satisfy<I, Pred>
    where I: Stream<Item=char>, Pred: FnMut(char) -> bool {

    type Input = I;
    type Output = char;
    fn parse_state(&mut self, input: State<I>) -> ParseResult<char, I> {
        match input.clone().uncons_char() {
            Ok((c, s)) => {
                if (self.pred)(c) { Ok((c, s)) }
                else {
                    Err(Consumed::Empty(ParseError::new(input.position, Error::Unexpected(c))))
                }
            }
            Err(err) => Err(err)
        }
    }
}

///Parses a character and succeeds depending on the result of `pred`
///
/// ```
/// # extern crate "parser-combinators" as pc;
/// # use pc::*;
/// # fn main() {
/// let result = satisfy(|c| c == '!')
///     .parse("!")
///     .map(|x| x.0);
/// assert_eq!(result, Ok('!'));
/// # }
/// ```
pub fn satisfy<I, Pred>(pred: Pred) -> Satisfy<I, Pred>
    where I: Stream<Item=char>, Pred: FnMut(char) -> bool {
    Satisfy { pred: pred }
}

impl_char_parser! { Digit(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses a digit from a stream containing characters
pub fn digit<I>() -> Digit<I>
    where I: Stream<Item=char> {
    Digit(satisfy(static_fn!((c, char) -> bool { c.is_digit(10) }))
         .expected("digit"))
}

impl_char_parser! { Space(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses whitespace
pub fn space<I>() -> Space<I>
    where I: Stream<Item=char> {
    Space(satisfy(CharExt::is_whitespace as fn (char) -> bool)
        .expected("whitespace"))
}
impl_char_parser! { Spaces(), Expected<SkipMany<Space<I>>> }
///Skips over zero or more spaces
pub fn spaces<I>() -> Spaces<I>
    where I: Stream<Item=char> {
    Spaces(skip_many(space())
          .expected("whitespaces"))
}

impl_char_parser! { NewLine(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses a newline character
pub fn newline<I>() -> NewLine<I>
    where I: Stream<Item=char> {
    NewLine(satisfy(static_fn!((ch, char) -> bool { ch == '\n' }))
           .expected("lf newline"))
}

impl_char_parser! { CrLf(), Expected<With<Satisfy<I, fn (char) -> bool>, NewLine<I>>> }
///Parses carriage return and newline, returning the newline character.
pub fn crlf<I>() -> CrLf<I>
    where I: Stream<Item=char> {
    CrLf(satisfy(static_fn!((ch, char) -> bool { ch == '\r' }))
        .with(newline())
        .expected("crlf newline"))
}

impl_char_parser! { Tab(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses a tab character
pub fn tab<I>() -> Tab<I>
    where I: Stream<Item=char> {
    Tab(satisfy(static_fn!((ch, char) -> bool { ch == '\t' }))
       .expected("tab"))
}

impl_char_parser! { Upper(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses an uppercase letter
pub fn upper<I>() -> Upper<I>
    where I: Stream<Item=char> {
    Upper(satisfy(static_fn!((ch, char) -> bool { ch.is_uppercase()}))
         .expected("uppercase letter"))
}

impl_char_parser! { Lower(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses an uppercase letter
pub fn lower<I>() -> Lower<I>
    where I: Stream<Item=char> {
    Lower(satisfy(static_fn!((ch, char) -> bool { ch.is_lowercase() }))
         .expected("lowercase letter"))
}

impl_char_parser! { AlphaNum(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses either an alphabet letter or digit
pub fn alpha_num<I>() -> AlphaNum<I>
    where I: Stream<Item=char> {
    AlphaNum(satisfy(static_fn!((ch, char) -> bool { ch.is_alphanumeric() }))
            .expected("letter or digit"))
}

impl_char_parser! { Letter(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses an alphabet letter
pub fn letter<I>() -> Letter<I>
    where I: Stream<Item=char> {
    Letter(satisfy(static_fn!((ch, char) -> bool { ch.is_alphabetic() }))
          .expected("letter"))
}

impl_char_parser! { OctDigit(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses an octal digit
pub fn oct_digit<I>() -> OctDigit<I>
    where I: Stream<Item=char> {
    OctDigit(satisfy(static_fn!((ch, char) -> bool { ch.is_digit(8) }))
            .expected("octal digit"))
}

impl_char_parser! { HexDigit(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses a hexdecimal digit with uppercase and lowercase
pub fn hex_digit<I>() -> HexDigit<I>
    where I: Stream<Item=char> {
    HexDigit(satisfy(static_fn!((ch, char) -> bool { ch.is_digit(0x10) }))
            .expected("hexadecimal digit"))
}

#[derive(Clone)]
pub struct String<I>(&'static str);
impl <I> Parser for String<I>
    where I: Stream<Item=char> {
    type Input = I;
    type Output = &'static str;
    fn parse_state(&mut self, mut input: State<I>) -> ParseResult<&'static str, I> {
        let start = input.position;
        let mut consumed = false;
        for c in self.0.chars() {
            match input.uncons_char() {
                Ok((other, rest)) => {
                    if c != other {
                        let error = ParseError::new(start, Error::Expected(self.0.into_cow()));
                        return Err(if consumed { Consumed::Consumed(error) } else { Consumed::Empty(error) })
                    }
                    consumed = true;
                    input = rest;
                }
                Err(mut error) => {
                    error.position = start;
                    return Err(if consumed { Consumed::Consumed(error) } else { Consumed::Empty(error) })
                }
            }
        }
        Ok((self.0, input))
    }
}

///Parses the string `s`
///
/// ```
/// # extern crate "parser-combinators" as pc;
/// # use pc::*;
/// # fn main() {
/// let result = string("rust")
///     .parse("rust")
///     .map(|x| x.0);
/// assert_eq!(result, Ok("rust"));
/// # }
/// ```
pub fn string<I>(s: &'static str) -> String<I>
    where I: Stream<Item=char> {
    String(s)
}

#[cfg(test)]
mod tests {
    use super::*;
    use primitives::{Error, Parser, SourcePosition};
    use std::borrow::IntoCow;

    #[test]
    fn space_error() {
        let result = space()
            .parse("");
        assert!(result.is_err());
        assert_eq!(result.unwrap_err().errors, vec![Error::Message("End of input".into_cow()), Error::Expected("whitespace".into_cow())]);

    }

    #[test]
    fn string_consumed() {
        let result = string("a").parse("b");
        assert!(result.is_err());
        assert_eq!(result.unwrap_err().position, SourcePosition { line: 1, column: 1 });
    }
}
<commit_msg>Fix accidentally breaking the build<commit_after>use primitives::{Consumed, Parser, ParseError, ParseResult, Error, State, Stream};
use combinator::{Expected, skip_many, SkipMany, ParserExt, With};
use std::borrow::IntoCow;

macro_rules! impl_char_parser {
    ($name: ident ($($ty_var: ident),*), $inner_type: ty) => {
    #[derive(Clone)]
    pub struct $name<I $(,$ty_var)*>($inner_type)
        where I: Stream<Item=char> $(, $ty_var : Parser<Input=I>)*;
    impl <I $(,$ty_var)*> Parser for $name<I $(,$ty_var)*>
        where I: Stream<Item=char> $(, $ty_var : Parser<Input=I>)* {
        type Input = I;
        type Output = <$inner_type as Parser>::Output;
        fn parse_state(&mut self, input: State<<Self as Parser>::Input>) -> ParseResult<<Self as Parser>::Output, <Self as Parser>::Input> {
            self.0.parse_state(input)
        }
    }
}
}

///Parses any character
pub fn any_char<I>(input: State<I>) -> ParseResult<char, I>
    where I: Stream<Item=char> {
    input.uncons_char()
}

#[derive(Clone)]
pub struct Satisfy<I, Pred> { pred: Pred }

impl <I, Pred> Parser for Satisfy<I, Pred>
    where I: Stream<Item=char>, Pred: FnMut(char) -> bool {

    type Input = I;
    type Output = char;
    fn parse_state(&mut self, input: State<I>) -> ParseResult<char, I> {
        match input.clone().uncons_char() {
            Ok((c, s)) => {
                if (self.pred)(c) { Ok((c, s)) }
                else {
                    Err(Consumed::Empty(ParseError::new(input.position, Error::Unexpected(c))))
                }
            }
            Err(err) => Err(err)
        }
    }
}

///Parses a character and succeeds depending on the result of `pred`
///
/// ```
/// # extern crate "parser-combinators" as pc;
/// # use pc::*;
/// # fn main() {
/// let result = satisfy(|c| c == '!')
///     .parse("!")
///     .map(|x| x.0);
/// assert_eq!(result, Ok('!'));
/// # }
/// ```
pub fn satisfy<I, Pred>(pred: Pred) -> Satisfy<I, Pred>
    where I: Stream<Item=char>, Pred: FnMut(char) -> bool {
    Satisfy { pred: pred }
}

impl_char_parser! { Digit(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses a digit from a stream containing characters
pub fn digit<I>() -> Digit<I>
    where I: Stream<Item=char> {
    Digit(satisfy(static_fn!((c, char) -> bool { c.is_digit(10) }))
         .expected("digit"))
}

impl_char_parser! { Space(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses whitespace
pub fn space<I>() -> Space<I>
    where I: Stream<Item=char> {
    Space(satisfy(CharExt::is_whitespace as fn (char) -> bool)
        .expected("whitespace"))
}
impl_char_parser! { Spaces(), Expected<SkipMany<Space<I>>> }
///Skips over zero or more spaces
pub fn spaces<I>() -> Spaces<I>
    where I: Stream<Item=char> {
    Spaces(skip_many(space())
          .expected("whitespaces"))
}

impl_char_parser! { NewLine(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses a newline character
pub fn newline<I>() -> NewLine<I>
    where I: Stream<Item=char> {
    NewLine(satisfy(static_fn!((ch, char) -> bool { ch == '\n' }))
           .expected("lf newline"))
}

impl_char_parser! { CrLf(), Expected<With<Satisfy<I, fn (char) -> bool>, NewLine<I>>> }
///Parses carriage return and newline, returning the newline character.
pub fn crlf<I>() -> CrLf<I>
    where I: Stream<Item=char> {
    CrLf(satisfy(static_fn!((ch, char) -> bool { ch == '\r' }))
        .with(newline())
        .expected("crlf newline"))
}

impl_char_parser! { Tab(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses a tab character
pub fn tab<I>() -> Tab<I>
    where I: Stream<Item=char> {
    Tab(satisfy(static_fn!((ch, char) -> bool { ch == '\t' }))
       .expected("tab"))
}

impl_char_parser! { Upper(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses an uppercase letter
pub fn upper<I>() -> Upper<I>
    where I: Stream<Item=char> {
    Upper(satisfy(static_fn!((ch, char) -> bool { ch.is_uppercase()}))
         .expected("uppercase letter"))
}

impl_char_parser! { Lower(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses an uppercase letter
pub fn lower<I>() -> Lower<I>
    where I: Stream<Item=char> {
    Lower(satisfy(static_fn!((ch, char) -> bool { ch.is_lowercase() }))
         .expected("lowercase letter"))
}

impl_char_parser! { AlphaNum(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses either an alphabet letter or digit
pub fn alpha_num<I>() -> AlphaNum<I>
    where I: Stream<Item=char> {
    AlphaNum(satisfy(static_fn!((ch, char) -> bool { ch.is_alphanumeric() }))
            .expected("letter or digit"))
}

impl_char_parser! { Letter(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses an alphabet letter
pub fn letter<I>() -> Letter<I>
    where I: Stream<Item=char> {
    Letter(satisfy(static_fn!((ch, char) -> bool { ch.is_alphabetic() }))
          .expected("letter"))
}

impl_char_parser! { OctDigit(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses an octal digit
pub fn oct_digit<I>() -> OctDigit<I>
    where I: Stream<Item=char> {
    OctDigit(satisfy(static_fn!((ch, char) -> bool { ch.is_digit(8) }))
            .expected("octal digit"))
}

impl_char_parser! { HexDigit(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses a hexdecimal digit with uppercase and lowercase
pub fn hex_digit<I>() -> HexDigit<I>
    where I: Stream<Item=char> {
    HexDigit(satisfy(static_fn!((ch, char) -> bool { ch.is_digit(0x10) }))
            .expected("hexadecimal digit"))
}

#[derive(Clone)]
pub struct String<I>(&'static str);
impl <I> Parser for String<I>
    where I: Stream<Item=char> {
    type Input = I;
    type Output = &'static str;
    fn parse_state(&mut self, mut input: State<I>) -> ParseResult<&'static str, I> {
        let start = input.position;
        let mut consumed = false;
        for c in self.0.chars() {
            match input.uncons_char() {
                Ok((other, rest)) => {
                    if c != other {
                        let error = ParseError::new(start, Error::Expected(self.0.into_cow()));
                        return Err(if consumed { Consumed::Consumed(error) } else { Consumed::Empty(error) })
                    }
                    consumed = true;
                    input = rest.into_inner();
                }
                Err(error) => {
                    return error.combine(|mut error| {
                        error.position = start;
                        Err(if consumed { Consumed::Consumed(error) } else { Consumed::Empty(error) })
                    })
                }
            }
        }
        Ok((self.0, if consumed { Consumed::Consumed(input) } else { Consumed::Empty(input) }))
    }
}

///Parses the string `s`
///
/// ```
/// # extern crate "parser-combinators" as pc;
/// # use pc::*;
/// # fn main() {
/// let result = string("rust")
///     .parse("rust")
///     .map(|x| x.0);
/// assert_eq!(result, Ok("rust"));
/// # }
/// ```
pub fn string<I>(s: &'static str) -> String<I>
    where I: Stream<Item=char> {
    String(s)
}

#[cfg(test)]
mod tests {
    use super::*;
    use primitives::{Error, Parser, SourcePosition};
    use std::borrow::IntoCow;

    #[test]
    fn space_error() {
        let result = space()
            .parse("");
        assert!(result.is_err());
        assert_eq!(result.unwrap_err().errors, vec![Error::Message("End of input".into_cow()), Error::Expected("whitespace".into_cow())]);

    }

    #[test]
    fn string_consumed() {
        let result = string("a").parse("b");
        assert!(result.is_err());
        assert_eq!(result.unwrap_err().position, SourcePosition { line: 1, column: 1 });
    }
}
<|endoftext|>


<commit_before>// Demonstration of the hackrf crate
// Copyright Adam Greig <adam@adamgreig.com> 2014
// Licensed under MIT license

extern crate hackrf;

fn main() {
    hackrf::init().unwrap();

    println!("Opening device.");
    let mut device = hackrf::open().unwrap();

    let board_id = hackrf::board_id_read(&mut device).unwrap();
    println!("Board ID: {}", board_id);

    let board_version = hackrf::version_string_read(&mut device).unwrap();
    println!("Board version: {}", board_version);

    let serial = hackrf::board_partid_serialno_read(&mut device);
    let (partid, serialno) = serial.unwrap();
    println!("Board part ID {}, serial number {}", partid, serialno);

    println!("Tuning to IF 2.2GHz, LO 100MHz, filter bypass");
    hackrf::set_freq_explicit(&mut device, 2_200_000_000, 100_000_000,
                              hackrf::RFPathFilter::Bypass).unwrap();

    println!("Tuning to 434MHz");
    hackrf::set_freq(&mut device, 434_000_000).unwrap();

    println!("Setting sample rate to 8Msps");
    hackrf::set_sample_rate(&mut device, 8e6).unwrap();

    println!("Setting sample rate to 16Msps/2");
    hackrf::set_sample_rate_manual(&mut device, 16_000_000, 2).unwrap();

    println!("Disabling power amplifier");
    hackrf::set_amp_enable(&mut device, false).unwrap();

    println!("Setting LNA gain to 2 (=16dB)")
    hackrf::set_lna_gain(&mut device, 0).unwrap();

    println!("Setting VGA gain to 4 (=8dB)")
    hackrf::set_vga_gain(&mut device, 32).unwrap();

    println!("Setting TXVGA gain to 6 (=6dB)")
    hackrf::set_txvga_gain(&mut device, 12).unwrap();

    println!("Disabling antenna power")
    hackrf::set_antenna_enable(&mut device, false).unwrap();

    let bw1 = hackrf::compute_baseband_filter_bw_round_down_lt(2000);
    println!("bw1={}", bw1);

    let bw2 = hackrf::compute_baseband_filter_bw(2000);
    println!("bw2={}", bw2);

    println!("Setting up RX stream");
    let mut rx_cb = |_: &[u8]| -> bool {
        println!("rx cb");
        true
    };
    hackrf::start_rx(&mut device, &mut rx_cb).unwrap();
    std::io::timer::sleep(std::time::duration::Duration::milliseconds(200));
    println!("Stopping RX stream");
    hackrf::stop_rx(&mut device).unwrap();

    println!("Re-opening");
    hackrf::close(device).unwrap();
    let mut device = hackrf::open().unwrap();

    println!("Setting up TX stream");
    let mut tx_cb = |_: &mut[u8]| -> bool {
        println!("tx cb");
        true
    };
    hackrf::start_tx(&mut device, &mut tx_cb).unwrap();
    std::io::timer::sleep(std::time::duration::Duration::milliseconds(200));
    println!("Stopping TX stream");
    hackrf::stop_tx(&mut device).unwrap();

    println!("Closing device.");
    hackrf::close(device).unwrap();

    hackrf::exit().unwrap();
}
<commit_msg>add trailing semicolons. how did i miss this...<commit_after>// Demonstration of the hackrf crate
// Copyright Adam Greig <adam@adamgreig.com> 2014
// Licensed under MIT license

extern crate hackrf;

fn main() {
    hackrf::init().unwrap();

    println!("Opening device.");
    let mut device = hackrf::open().unwrap();

    let board_id = hackrf::board_id_read(&mut device).unwrap();
    println!("Board ID: {}", board_id);

    let board_version = hackrf::version_string_read(&mut device).unwrap();
    println!("Board version: {}", board_version);

    let serial = hackrf::board_partid_serialno_read(&mut device);
    let (partid, serialno) = serial.unwrap();
    println!("Board part ID {}, serial number {}", partid, serialno);

    println!("Tuning to IF 2.2GHz, LO 100MHz, filter bypass");
    hackrf::set_freq_explicit(&mut device, 2_200_000_000, 100_000_000,
                              hackrf::RFPathFilter::Bypass).unwrap();

    println!("Tuning to 434MHz");
    hackrf::set_freq(&mut device, 434_000_000).unwrap();

    println!("Setting sample rate to 8Msps");
    hackrf::set_sample_rate(&mut device, 8e6).unwrap();

    println!("Setting sample rate to 16Msps/2");
    hackrf::set_sample_rate_manual(&mut device, 16_000_000, 2).unwrap();

    println!("Disabling power amplifier");
    hackrf::set_amp_enable(&mut device, false).unwrap();

    println!("Setting LNA gain to 2 (=16dB)");
    hackrf::set_lna_gain(&mut device, 0).unwrap();

    println!("Setting VGA gain to 4 (=8dB)");
    hackrf::set_vga_gain(&mut device, 32).unwrap();

    println!("Setting TXVGA gain to 6 (=6dB)");
    hackrf::set_txvga_gain(&mut device, 12).unwrap();

    println!("Disabling antenna power");
    hackrf::set_antenna_enable(&mut device, false).unwrap();

    let bw1 = hackrf::compute_baseband_filter_bw_round_down_lt(2000);
    println!("bw1={}", bw1);

    let bw2 = hackrf::compute_baseband_filter_bw(2000);
    println!("bw2={}", bw2);

    println!("Setting up RX stream");
    let mut rx_cb = |_: &[u8]| -> bool {
        println!("rx cb");
        true
    };
    hackrf::start_rx(&mut device, &mut rx_cb).unwrap();
    std::io::timer::sleep(std::time::duration::Duration::milliseconds(200));
    println!("Stopping RX stream");
    hackrf::stop_rx(&mut device).unwrap();

    println!("Re-opening");
    hackrf::close(device).unwrap();
    let mut device = hackrf::open().unwrap();

    println!("Setting up TX stream");
    let mut tx_cb = |_: &mut[u8]| -> bool {
        println!("tx cb");
        true
    };
    hackrf::start_tx(&mut device, &mut tx_cb).unwrap();
    std::io::timer::sleep(std::time::duration::Duration::milliseconds(200));
    println!("Stopping TX stream");
    hackrf::stop_tx(&mut device).unwrap();

    println!("Closing device.");
    hackrf::close(device).unwrap();

    hackrf::exit().unwrap();
}
<|endoftext|>