<commit_before>#![allow(dead_code)]

use std::mem;

use llvm_sys::core;
use llvm_sys::prelude::{
  LLVMBuilderRef,
  LLVMValueRef
};
use libc::{c_char, c_uint};

use types::Ty;
use block::BasicBlock;
use value::{Function, Value, PhiNode};

static NULL_NAME:[c_char; 1] = [0];

pub struct Builder(pub LLVMBuilderRef);
impl_dispose!(Builder, core::LLVMDisposeBuilder);

impl Builder {

  pub fn get_insert_block(&self) -> BasicBlock
  {
    BasicBlock(unsafe { core::LLVMGetInsertBlock(self.0)})
  }

  /// Position the builder at `instr` within `block`.
  pub fn position_at(&self, block: &BasicBlock, instr: &Value)
  {
    unsafe { core::LLVMPositionBuilder(self.0, block.0, instr.0) }
  }

  /// Position the builder at the end of `block`.
  pub fn position_at_end(&self, block: &BasicBlock)
  {
    unsafe { core::LLVMPositionBuilderAtEnd(self.0, block.0) }
  }

  /// Build an instruction that returns from the function with void.
  pub fn create_ret_void(&self) -> Value
  {
    Value(unsafe {core::LLVMBuildRetVoid(self.0)})
  }

  /// Build an instruction that returns from the function with `value`.
  pub fn create_ret(&self, value: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildRet(self.0, value.0)})
  }

  /// Build an instruction that allocates an array with the element type `elem` and
  /// the size `size`.
  ///
  /// The size of this array will be the size of `elem` times `size`.
  pub fn build_array_alloca(&self, elem: &Ty, size: &Value) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildArrayAlloca(self.0,
    														 elem.0,
    														 size.0,
    														 NULL_NAME.as_ptr() as *const c_char)
    })
  }

  /// Build an instruction that allocates a pointer to fit the size of `ty` then returns this
  /// pointer.
  ///
  /// Make sure to call `build_free` with the pointer value when you're done with it, or you're
  /// gonna have a bad time.
  pub fn create_alloca(&self, ty: &Ty) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildAlloca(self.0,
    												ty.0,
    												NULL_NAME.as_ptr() as *const c_char)
    })
  }

  /// Build an instruction that frees the `val`, which _MUST_ be a pointer that was returned
  /// from `build_alloca`.
  pub fn create_free(&self, val: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildFree(self.0, val.0) })
  }

  /// Build an instruction that store the value `val` in the pointer `ptr`.
  pub fn create_store(&self, val: &Value, ptr: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildStore(self.0, val.0, ptr.0) })
  }

  /// Build an instruction that branches to the block `dest`.
  pub fn create_br(&self, dest: &BasicBlock) -> Value
  {
    Value(unsafe { core::LLVMBuildBr(self.0, dest.0)})
  }

  /// Build an instruction that branches to `if_block` if `cond` evaluates to true, and
  /// `else_block` otherwise.
  pub fn create_cond_br(&self, cond: &Value,
  	                    if_block: &BasicBlock, else_block: Option<&BasicBlock>) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildCondBr(self.0,
    		                    cond.0,
    		                    if_block.0,
    		                    mem::transmute(else_block))
    })
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  fn create_call_internal(&self, func: &Function, args: &[&Value], tail_call: bool) -> Value
  {
    let ref_array = to_llvmref_array!(args, LLVMValueRef);

    Value(unsafe {
        let call = core::LLVMBuildCall(self.0,
        	                             func.0,
                                       ref_array.as_ptr() as *mut LLVMValueRef,
        	                             args.len() as c_uint,
        	                             NULL_NAME.as_ptr());
        core::LLVMSetTailCall(call, if tail_call {1} else {0});
        call.into()
    })
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_call(&self, func: &Function, args: &[&Value]) -> Value
  {
    self.create_call_internal(func, args, false)
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_tail_call(&self, func: &Function, args: &[&Value]) -> Value
  {
    self.create_call_internal(func, args, true)
  }

  /// Build an instruction that yields to `true_val` if `cond` is equal to `1`, and `false_val`
  /// otherwise.
  pub fn create_select(&self, cond: &Value, true_val: &Value, false_val: &Value) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildSelect(self.0,
    		                    cond.0,
    		                    true_val.0,
    		                    false_val.0,
    		                    NULL_NAME.as_ptr()) })
  }

  /// Build an instruction that casts a value into a certain type.
  pub fn create_bit_cast(&self, value: &Value, dest: &Ty) -> Value
  {
    Value(unsafe { core::LLVMBuildBitCast(
    		self.0,
    		value.0,
    		dest.0,
    		NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction that inserts a value into an aggregate data value.
  pub fn create_insert_value(&self, agg: &Value, elem: &Value, index: usize) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildInsertValue(self.0,
    		                         agg.0,
    		                         elem.0,
    		                         index as c_uint,
    		                         NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction that extracts a value from an aggregate type.
	pub fn create_extract_value(&self, agg: &Value, index: usize) -> Value {
    Value(unsafe {
    	core::LLVMBuildExtractValue(self.0,
    		                          agg.0,
    		                          index as c_uint,
    		                          NULL_NAME.as_ptr())
   	})
  }

  /// Build an instruction that computes the address of a subelement of an aggregate data
  /// structure.
  ///
  /// Basically type-safe pointer arithmetic.
  pub fn create_gep(&self, pointer: &Value, indices: &[&Value]) -> Value
  {
    let ref_array = to_llvmref_array!(indices, LLVMValueRef);

    Value(unsafe {
    	core::LLVMBuildInBoundsGEP(self.0,
    	                           pointer.0,
    	                           ref_array.as_ptr() as *mut LLVMValueRef,
    	                           indices.len() as c_uint,
    	                           NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction to select a value depending on the predecessor of the current block.
  pub fn create_phi(&self, ty: &Ty, name: &str) -> PhiNode
  {
	  PhiNode(unsafe {
	  	core::LLVMBuildPhi(self.0, ty.0, ::util::chars::from_str(name))
  	})
  }

  /// Build an instruction that runs whichever block matches the value, or `default` if none of
  /// them matched it.
  pub fn create_switch(&self,
  	                   value: &Value,
  	                   default: &BasicBlock,
  	                   cases: &[(&Value, &BasicBlock)]) -> Value {
    Value(unsafe {
      let switch = core::LLVMBuildSwitch(self.0,
      	                                 value.0,
      	                                 default.0,
      	                                 cases.len() as c_uint);
      for case in cases {
        core::LLVMAddCase(switch, (case.0).0, (case.1).0);
      }

      switch
    })
  }
}<commit_msg>Add condition br unit test to builder.rs.<commit_after>#![allow(dead_code)]

use std::mem;

use llvm_sys::core;
use llvm_sys::prelude::{
  LLVMBuilderRef,
  LLVMValueRef
};
use libc::{c_char, c_uint};

use types::Ty;
use block::BasicBlock;
use value::{Function, Value, PhiNode};

static NULL_NAME:[c_char; 1] = [0];

pub struct Builder(pub LLVMBuilderRef);
impl_dispose!(Builder, core::LLVMDisposeBuilder);

impl Builder {

  pub fn get_insert_block(&self) -> BasicBlock
  {
    BasicBlock(unsafe { core::LLVMGetInsertBlock(self.0)})
  }

  /// Position the builder at `instr` within `block`.
  pub fn position_at(&self, block: &BasicBlock, instr: &Value)
  {
    unsafe { core::LLVMPositionBuilder(self.0, block.0, instr.0) }
  }

  /// Position the builder at the end of `block`.
  pub fn position_at_end(&self, block: &BasicBlock)
  {
    unsafe { core::LLVMPositionBuilderAtEnd(self.0, block.0) }
  }

  /// Build an instruction that returns from the function with void.
  pub fn create_ret_void(&self) -> Value
  {
    Value(unsafe {core::LLVMBuildRetVoid(self.0)})
  }

  /// Build an instruction that returns from the function with `value`.
  pub fn create_ret(&self, value: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildRet(self.0, value.0)})
  }

  /// Build an instruction that allocates an array with the element type `elem` and
  /// the size `size`.
  ///
  /// The size of this array will be the size of `elem` times `size`.
  pub fn build_array_alloca(&self, elem: &Ty, size: &Value) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildArrayAlloca(self.0,
    														 elem.0,
    														 size.0,
    														 NULL_NAME.as_ptr() as *const c_char)
    })
  }

  /// Build an instruction that allocates a pointer to fit the size of `ty` then returns this
  /// pointer.
  ///
  /// Make sure to call `build_free` with the pointer value when you're done with it, or you're
  /// gonna have a bad time.
  pub fn create_alloca(&self, ty: &Ty) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildAlloca(self.0,
    												ty.0,
    												NULL_NAME.as_ptr() as *const c_char)
    })
  }

  /// Build an instruction that frees the `val`, which _MUST_ be a pointer that was returned
  /// from `build_alloca`.
  pub fn create_free(&self, val: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildFree(self.0, val.0) })
  }

  /// Build an instruction that store the value `val` in the pointer `ptr`.
  pub fn create_store(&self, val: &Value, ptr: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildStore(self.0, val.0, ptr.0) })
  }

  /// Build an instruction that branches to the block `dest`.
  pub fn create_br(&self, dest: &BasicBlock) -> Value
  {
    Value(unsafe { core::LLVMBuildBr(self.0, dest.0)})
  }

  /// Build an instruction that branches to `if_block` if `cond` evaluates to true, and
  /// `else_block` otherwise.
  pub fn create_cond_br(&self, cond: &Value,
  	                    if_block: &BasicBlock, else_block: Option<&BasicBlock>) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildCondBr(self.0,
    		                    cond.0,
    		                    if_block.0,
    		                    mem::transmute(else_block))
    })
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  fn create_call_internal(&self, func: &Function, args: &[&Value], tail_call: bool) -> Value
  {
    let ref_array = to_llvmref_array!(args, LLVMValueRef);

    Value(unsafe {
        let call = core::LLVMBuildCall(self.0,
        	                             func.0,
                                       ref_array.as_ptr() as *mut LLVMValueRef,
        	                             args.len() as c_uint,
        	                             NULL_NAME.as_ptr());
        core::LLVMSetTailCall(call, if tail_call {1} else {0});
        call.into()
    })
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_call(&self, func: &Function, args: &[&Value]) -> Value
  {
    self.create_call_internal(func, args, false)
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_tail_call(&self, func: &Function, args: &[&Value]) -> Value
  {
    self.create_call_internal(func, args, true)
  }

  /// Build an instruction that yields to `true_val` if `cond` is equal to `1`, and `false_val`
  /// otherwise.
  pub fn create_select(&self, cond: &Value, true_val: &Value, false_val: &Value) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildSelect(self.0,
    		                    cond.0,
    		                    true_val.0,
    		                    false_val.0,
    		                    NULL_NAME.as_ptr()) })
  }

  /// Build an instruction that casts a value into a certain type.
  pub fn create_bit_cast(&self, value: &Value, dest: &Ty) -> Value
  {
    Value(unsafe { core::LLVMBuildBitCast(
    		self.0,
    		value.0,
    		dest.0,
    		NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction that inserts a value into an aggregate data value.
  pub fn create_insert_value(&self, agg: &Value, elem: &Value, index: usize) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildInsertValue(self.0,
    		                         agg.0,
    		                         elem.0,
    		                         index as c_uint,
    		                         NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction that extracts a value from an aggregate type.
	pub fn create_extract_value(&self, agg: &Value, index: usize) -> Value {
    Value(unsafe {
    	core::LLVMBuildExtractValue(self.0,
    		                          agg.0,
    		                          index as c_uint,
    		                          NULL_NAME.as_ptr())
   	})
  }

  /// Build an instruction that computes the address of a subelement of an aggregate data
  /// structure.
  ///
  /// Basically type-safe pointer arithmetic.
  pub fn create_gep(&self, pointer: &Value, indices: &[&Value]) -> Value
  {
    let ref_array = to_llvmref_array!(indices, LLVMValueRef);

    Value(unsafe {
    	core::LLVMBuildInBoundsGEP(self.0,
    	                           pointer.0,
    	                           ref_array.as_ptr() as *mut LLVMValueRef,
    	                           indices.len() as c_uint,
    	                           NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction to select a value depending on the predecessor of the current block.
  pub fn create_phi(&self, ty: &Ty, name: &str) -> PhiNode
  {
	  PhiNode(unsafe {
	  	core::LLVMBuildPhi(self.0, ty.0, ::util::chars::from_str(name))
  	})
  }

  /// Build an instruction that runs whichever block matches the value, or `default` if none of
  /// them matched it.
  pub fn create_switch(&self,
  	                   value: &Value,
  	                   default: &BasicBlock,
  	                   cases: &[(&Value, &BasicBlock)]) -> Value {
    Value(unsafe {
      let switch = core::LLVMBuildSwitch(self.0,
      	                                 value.0,
      	                                 default.0,
      	                                 cases.len() as c_uint);
      for case in cases {
        core::LLVMAddCase(switch, (case.0).0, (case.1).0);
      }

      switch
    })
  }
}

#[cfg(test)]
mod tests {
	use super::*;
  use super::super::*;
  use types::LLVMTy;

	#[test]
	pub fn test_cond_br()
	{
		let jit = JitCompiler::new("test1").ok().unwrap();
    let ctx = jit.context();

    let func_ty = jit.create_func_ty(&f64::llvm_ty(ctx), &[&f64::llvm_ty(ctx)]);
    let func = jit.add_func("fib", &func_ty);
    let value = func.arg(0);

    let entry = func.append("entry");
    let then_bb = func.append("then_block");
    let else_bb = func.append("else_block");
    let merge_bb = func.append("merge_block");

    let builder = jit.builder();
    builder.position_at_end(&entry);

    let local = builder.create_alloca(&u64::llvm_ty(&ctx));

    let cond = builder.create_cmp(&value, 5u64.to_value(&ctx), Predicate::LessThan);
	}
}<|endoftext|>


<commit_before>use bot::LalafellBot;
use filters::Filter;

use lalafell::bot::Bot;
use lalafell::commands::prelude::*;

use discord::model::{Message, LiveServer, PublicChannel};
use discord::model::permissions;

use std::sync::Arc;

const USAGE: &'static str = "!search <filters>";

pub struct SearchCommand {
  bot: Arc<LalafellBot>
}

impl SearchCommand {
  pub fn new(bot: Arc<LalafellBot>) -> SearchCommand {
    SearchCommand {
      bot
    }
  }
}

impl HasBot for SearchCommand {
  fn bot(&self) -> &Bot {
    self.bot.as_ref()
  }
}

#[derive(Debug, Deserialize)]
pub struct Params {
  filter_strings: Vec<String>
}

impl HasParams for SearchCommand {
  type Params = Params;
}

impl<'a> PublicChannelCommand<'a> for SearchCommand {
  fn run(&self, message: &Message, server: &LiveServer, channel: &PublicChannel, params: &[&str]) -> CommandResult<'a> {
    let params = self.params(USAGE, params)?;

    let can_manage_roles = server.permissions_for(channel.id, message.author.id).contains(permissions::MANAGE_ROLES);
    if !can_manage_roles {
      return Err(ExternalCommandFailure::default()
        .message(|e: EmbedBuilder| e
          .title("Not enough permissions.")
          .description("You don't have enough permissions to use this command."))
        .wrap());
    }

    let filters: Vec<Filter> = match params.filter_strings.iter().map(|x| Filter::parse(x)).collect::<Option<_>>() {
      Some(f) => f,
      None => return Err("Invalid filter.".into())
    };
    let matches: Vec<String> = server.members.iter()
      .filter(|m| filters.iter().all(|f| f.matches(m, &server.roles)))
      .map(|m| m.user.mention().to_string())
      .collect();
    Ok(matches.join("\n").into())
  }
}
<commit_msg>feat: add join time to search command<commit_after>use bot::LalafellBot;
use filters::Filter;

use lalafell::bot::Bot;
use lalafell::commands::prelude::*;

use discord::model::{Message, LiveServer, PublicChannel};
use discord::model::permissions;

use chrono::DateTime;

use std::sync::Arc;

const USAGE: &'static str = "!search <filters>";

pub struct SearchCommand {
  bot: Arc<LalafellBot>
}

impl SearchCommand {
  pub fn new(bot: Arc<LalafellBot>) -> SearchCommand {
    SearchCommand {
      bot
    }
  }
}

impl HasBot for SearchCommand {
  fn bot(&self) -> &Bot {
    self.bot.as_ref()
  }
}

#[derive(Debug, Deserialize)]
pub struct Params {
  filter_strings: Vec<String>
}

impl HasParams for SearchCommand {
  type Params = Params;
}

impl<'a> PublicChannelCommand<'a> for SearchCommand {
  fn run(&self, message: &Message, server: &LiveServer, channel: &PublicChannel, params: &[&str]) -> CommandResult<'a> {
    let params = self.params(USAGE, params)?;

    let can_manage_roles = server.permissions_for(channel.id, message.author.id).contains(permissions::MANAGE_ROLES);
    if !can_manage_roles {
      return Err(ExternalCommandFailure::default()
        .message(|e: EmbedBuilder| e
          .title("Not enough permissions.")
          .description("You don't have enough permissions to use this command."))
        .wrap());
    }

    let filters: Vec<Filter> = match params.filter_strings.iter().map(|x| Filter::parse(x)).collect::<Option<_>>() {
      Some(f) => f,
      None => return Err("Invalid filter.".into())
    };
    let matches: Vec<String> = server.members.iter()
      .filter(|m| filters.iter().all(|f| f.matches(m, &server.roles)))
      .map(|m| format!("{} - {}",
        m.user.mention(),
        DateTime::parse_from_rfc3339(&m.joined_at).map(|d| d.format("%B %e, %Y %H:%M").to_string()).unwrap_or_else(|_| String::from("unknown"))))
      .collect();
    Ok(matches.join("\n").into())
  }
}
<|endoftext|>


<commit_before>//! The project module takes care of muxed related initialization. Locating the
/// users home directory. Finding the desired config files, and reading the
/// configs in.

use std::path::{Path, PathBuf};
use std::io::prelude::*;
use std::fs::File;
use yaml_rust::{YamlLoader, Yaml};
#[cfg(not(test))] use std::env::home_dir;
#[cfg(test)] use rand::random;
#[cfg(test)] use std::fs;

pub mod parser;
pub mod processor;

/// The muxed project folder name. Should be located in the users home dir as a
/// hidden directory.
static MUXED_FOLDER: &'static str = "muxed";

/// Using the provided project name, locate the path to that project file. It
/// should be something similar to: `~/.muxed/my_project.yml`
/// Read in the contents of the config (which should be Yaml), and parse the
/// contents as yaml.
///
/// # Examples
///
/// Given the project name "compiler" and a project file found at:
/// `~/.muxed/compiler.yml`.
///
/// ```
/// let yaml: Result<Vec<Yaml>, String> = read("compiler".to_string());
/// ```
///
/// project_name: The name of the project, corresponding to the project config
/// file.
pub fn read(project_name: &String) -> Result<Vec<Yaml>, String> {
    let home = try!(homedir().map_err(|e| e));
    let config = format!("{}/.{}/{}.yml", home.display(), &MUXED_FOLDER, project_name);
    let path = Path::new(&config);

    let mut file = try!(File::open(path).map_err(|e| format!("No project configuration file was found with the name `{}`. Received error: {}", project_name, e.to_string())));
    let mut contents = String::new();
    try!(file.read_to_string(&mut contents).map_err(|e| e.to_string()));

    let parsed_yaml = try!(YamlLoader::load_from_str(&contents).map_err(|e| e.to_string()));
    Ok(parsed_yaml)
}

/// Return the users homedir as a string.
#[cfg(not(test))] fn homedir() -> Result<PathBuf, String>{
    match home_dir() {
        Some(dir) => Ok(dir),
        None      => Err(String::from("We couldn't find your home directory."))
    }
}

/// Return the temp dir as the users home dir during testing.
#[cfg(test)] fn homedir() -> Result<PathBuf, String> {
    Ok(PathBuf::from("/tmp"))
}

#[test]
fn missing_file_returns_err() {
    let result = read(&String::from("not_a_file"));
    assert!(result.is_err())
}

#[test]
fn poorly_formatted_file_returns_err() {
    let name = format!("/tmp/{}.yml", random::<u16>());
    let path = Path::new(&name);
    let mut buffer = File::create(path).unwrap();
    let _ = buffer.write(b"some bytes");

    let result = read(&format!("{}", path.display()));
    assert!(result.is_err());
    let _ = fs::remove_file(path);
}
<commit_msg>Add a happy path test for file reading.<commit_after>//! The project module takes care of muxed related initialization. Locating the
/// users home directory. Finding the desired config files, and reading the
/// configs in.

use std::path::{Path, PathBuf};
use std::io::prelude::*;
use std::fs::File;
use yaml_rust::{YamlLoader, Yaml};
#[cfg(not(test))] use std::env::home_dir;
#[cfg(test)] use rand::random;
#[cfg(test)] use std::fs;

pub mod parser;
pub mod processor;

/// The muxed project folder name. Should be located in the users home dir as a
/// hidden directory.
static MUXED_FOLDER: &'static str = "muxed";

/// Using the provided project name, locate the path to that project file. It
/// should be something similar to: `~/.muxed/my_project.yml`
/// Read in the contents of the config (which should be Yaml), and parse the
/// contents as yaml.
///
/// # Examples
///
/// Given the project name "compiler" and a project file found at:
/// `~/.muxed/compiler.yml`.
///
/// ```
/// let yaml: Result<Vec<Yaml>, String> = read("compiler".to_string());
/// ```
///
/// project_name: The name of the project, corresponding to the project config
/// file.
pub fn read(project_name: &String) -> Result<Vec<Yaml>, String> {
    let home = try!(homedir().map_err(|e| e));
    let config = format!("{}/.{}/{}.yml", home.display(), &MUXED_FOLDER, project_name);
    let path = Path::new(&config);

    let mut file = try!(File::open(path).map_err(|e| format!("No project configuration file was found with the name `{}`. Received error: {}", project_name, e.to_string())));
    let mut contents = String::new();
    try!(file.read_to_string(&mut contents).map_err(|e| e.to_string()));

    let parsed_yaml = try!(YamlLoader::load_from_str(&contents).map_err(|e| e.to_string()));
    Ok(parsed_yaml)
}

/// Return the users homedir as a string.
#[cfg(not(test))] fn homedir() -> Result<PathBuf, String>{
    match home_dir() {
        Some(dir) => Ok(dir),
        None      => Err(String::from("We couldn't find your home directory."))
    }
}

/// Return the temp dir as the users home dir during testing.
#[cfg(test)] fn homedir() -> Result<PathBuf, String> {
    Ok(PathBuf::from("/tmp"))
}

#[test]
fn missing_file_returns_err() {
    let result = read(&String::from("not_a_file"));
    assert!(result.is_err())
}

#[test]
fn poorly_formatted_file_returns_err() {
    let name = format!("/tmp/{}.yml", random::<u16>());
    let path = Path::new(&name);
    let _ = fs::create_dir(Path::new("/tmp/.muxed/"));
    let mut buffer = File::create(path).unwrap();
    let _ = buffer.write(b"some bytes");

    let result = read(&format!("{}", path.display()));
    let _ = fs::remove_file(path);
    assert!(result.is_err());
}

#[test]
fn good_file_returns_ok() {
    let name = random::<u16>();
    let name1 = format!("/tmp/.muxed/{}.yml", name);
    let path = Path::new(&name1);
    let _ = fs::create_dir(Path::new("/tmp/.muxed/"));
    let mut buffer = File::create(path).unwrap();
    let _ = buffer.write(b"---
windows: ['cargo', 'vim', 'git']
");

    let result = read(&format!("{}", name));
    let _ = fs::remove_file(path);
    assert!(result.is_ok());
}
<|endoftext|>


<commit_before>#![feature(type_alias_impl_trait)]

trait IterBits {
    type BitsIter: Iterator<Item = u8>;
    fn iter_bits(self, n: u8) -> Self::BitsIter;
}

type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
//~^ ERROR could not find defining uses

impl<T, E> IterBits for T
where
    T: std::ops::Shr<Output = T>
        + std::ops::BitAnd<T, Output = T>
        + std::convert::From<u8>
        + std::convert::TryInto<u8, Error = E>,
    E: std::fmt::Debug,
{
    type BitsIter = IterBitsIter<T, E, u8>;
    fn iter_bits(self, n: u8) -> Self::BitsIter {
    //~^ ERROR defining opaque type use does not fully define opaque typ
        (0u8..n)
            .rev()
            .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
    }
}

fn main() {}
<commit_msg>Fix missing character<commit_after>#![feature(type_alias_impl_trait)]

trait IterBits {
    type BitsIter: Iterator<Item = u8>;
    fn iter_bits(self, n: u8) -> Self::BitsIter;
}

type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
//~^ ERROR could not find defining uses

impl<T, E> IterBits for T
where
    T: std::ops::Shr<Output = T>
        + std::ops::BitAnd<T, Output = T>
        + std::convert::From<u8>
        + std::convert::TryInto<u8, Error = E>,
    E: std::fmt::Debug,
{
    type BitsIter = IterBitsIter<T, E, u8>;
    fn iter_bits(self, n: u8) -> Self::BitsIter {
    //~^ ERROR defining opaque type use does not fully define opaque type
        (0u8..n)
            .rev()
            .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
    }
}

fn main() {}
<|endoftext|>


<commit_before>use std::io::BufferedReader;
use std::io::BufferedWriter;
use std::io::TcpStream;

struct IrcStream {
    inputstream: BufferedReader<TcpStream>,
    outputstream: BufferedWriter<TcpStream>,
    socket: TcpStream
}

impl IrcStream {
    pub fn new(host: &str, port: u16) -> IrcStream {
        let mut socket = TcpStream::connect((host, port)).unwrap();
        let mut reader = BufferedReader::new(socket.clone());
        let mut writer = BufferedWriter::new(socket.clone());
        let mut stream = IrcStream{ inputstream: reader, outputstream: writer, socket: socket };
        return stream;
    }

    pub fn read(&mut self) {
        loop {
            let next = self.inputstream.read_line();
            if next.is_err() {
                break;
            }
            let text = next.unwrap();
            print!("{}", text);
            if text.starts_with("ERROR") {
                break;
            }
            if text.starts_with("PING") {
                let pong = text.replace("PING ", "PONG ");
                self.write(pong.deref());
            }
        }
    }

    pub fn write(&mut self, line: &str) {
        print!("Writing: {}", line);
        self.outputstream.write_line(line);
        self.outputstream.flush();
    }

}<commit_msg>Adds comment.<commit_after>use std::io::BufferedReader;
use std::io::BufferedWriter;
use std::io::TcpStream;

struct IrcStream {
    inputstream: BufferedReader<TcpStream>,
    outputstream: BufferedWriter<TcpStream>,
    socket: TcpStream
}

impl IrcStream {
    pub fn new(host: &str, port: u16) -> IrcStream {
        let mut socket = TcpStream::connect((host, port)).unwrap();
        let mut reader = BufferedReader::new(socket.clone());
        let mut writer = BufferedWriter::new(socket.clone());
        let mut stream = IrcStream{ inputstream: reader, outputstream: writer, socket: socket };
        return stream;
    }

    pub fn read(&mut self) {
        loop {
            let next = self.inputstream.read_line();
            if next.is_err() {
                break;
            }
            let text = next.unwrap();
            print!("{}", text);
            if text.starts_with("ERROR") {
                break;
            }
            if text.starts_with("PING") {
                let pong = text.replace("PING ", "PONG ");
                self.write(pong.deref());
            }
        }
    }

    pub fn write(&mut self, line: &str) {
        print!("Writing: {}", line);
        self.outputstream.write_line(line);
        self.outputstream.flush(); // Maybe this shouldn't be a buffered output stream...?
    }

}<|endoftext|>


<commit_before>use std::str::Chars;

pub enum UsageToken<'u> {
    Name(&'u str, Option<bool>),
    Short(char),
    Long(&'u str),
    Help(&'u str),
    Multiple,
}

pub struct UsageParser<'u> {
    usage: &'u str,
    chars: Chars<'u>,
    s: usize,
    e: usize,
}

impl<'u> UsageParser<'u> {
    pub fn with_usage(u: &'u str) -> UsageParser<'u> {
        UsageParser {
            usage: u,
            chars: u.chars(),
            s: 0,
            e: 0,
        }
    }

}

impl<'u> Iterator for UsageParser<'u> {
    type Item = UsageToken<'u>;

    fn next(&mut self) -> Option<UsageToken<'u>> {
        loop {
            match self.chars.next() {
                Some(c) if c == '[' || c == '<' => {
                    // self.s = self.e + 1;
                    if self.e != 0 {
                        self.e += 1;
                    }
                    self.s = self.e + 1;
                    let closing = match c {
                        '[' => ']',
                        '<' => '>',
                        _ => unreachable!(),
                    };
                    while let Some(c) = self.chars.next() {
                        self.e += 1;
                        if c == closing {
                            break;
                        }
                    }
                    if self.e > self.usage.len() {
                        return None;
                    }

                    let name = &self.usage[self.s..self.e];

                    return Some(UsageToken::Name(name,
                                                 if c == '<' {
                                                     Some(true)
                                                 } else {
                                                     None
                                                 }));
                }
                Some('\'') => {
                    self.s = self.e + 2;
                    self.e = self.usage.len() - 1;

                    while let Some(_) = self.chars.next() {
                        continue;
                    }

                    return Some(UsageToken::Help(&self.usage[self.s..self.e]));
                }
                Some('-') => {
                    self.e += 1;
                    match self.chars.next() {
                        Some('-') => {
                            if self.e != 1 {
                                self.e += 1;
                            }

                            self.s = self.e + 1;

                            while let Some(c) = self.chars.next() {
                                self.e += 1;
                                if c == ' ' || c == '=' || c == '.' {
                                    break;
                                }
                            }
                            if self.e > self.usage.len() {
                                return None;
                            }

                            if self.e == self.usage.len() - 1 {
                                return Some(UsageToken::Long(&self.usage[self.s..]));
                            }
                            return Some(UsageToken::Long(&self.usage[self.s..self.e]));
                        }
                        Some(c) => {
                            // When short is first don't increment e
                            if self.e != 1 {
                                self.e += 1;
                            }
                            // Short
                            if !c.is_alphanumeric() {
                                return None;
                            }
                            return Some(UsageToken::Short(c));
                        }
                        _ => {
                            return None;
                        }
                    }
                }
                Some('.') => {
                    self.e += 1;
                    let mut mult = false;
                    for _ in 0..2 {
                        self.e += 1;
                        match self.chars.next() {
                            // longs consume one '.' so they match '.. ' whereas shorts can
                            // match '...'
                            Some('.') | Some(' ') => {
                                mult = true;
                            }
                            _ => {
                                // if there is no help or following space all we can match is '..'
                                if self.e == self.usage.len() - 1 {
                                    mult = true;
                                }
                                break;
                            }
                        }
                    }
                    if mult {
                        return Some(UsageToken::Multiple);
                    }
                }
                Some(' ') | Some('=') | Some(']') | Some('>') | Some('\t') | Some(',') => {
                    self.e += 1;
                    continue;
                }
                None => {
                    return None;
                }
                Some(c) => panic!("Usage parser error, unexpected \
                                  \"{}\" at \"{}\", check from_usage call",
                                  c,
                                  self.usage),
            }
        }
    }
}
<commit_msg>refactor(UsageParser): moves code for readability<commit_after>use std::str::Chars;

pub enum UsageToken<'u> {
    Name(&'u str, Option<bool>),
    Short(char),
    Long(&'u str),
    Help(&'u str),
    Multiple,
}

pub struct UsageParser<'u> {
    usage: &'u str,
    chars: Chars<'u>,
    s: usize,
    e: usize,
}

impl<'u> UsageParser<'u> {
    pub fn with_usage(u: &'u str) -> UsageParser<'u> {
        UsageParser {
            usage: u,
            chars: u.chars(),
            s: 0,
            e: 0,
        }
    }

    fn name(&mut self, c: char) -> Option<UsageToken<'u>> {
        if self.e != 0 {
            self.e += 1;
        }
        self.s = self.e + 1;
        let closing = match c {
            '[' => ']',
            '<' => '>',
            _ => unreachable!(),
        };
        while let Some(c) = self.chars.next() {
            self.e += 1;
            if c == closing {
                break;
            }
        }
        if self.e > self.usage.len() {
            return None;
        }

        let name = &self.usage[self.s..self.e];

        Some(UsageToken::Name(name,
                              if c == '<' {
                                  Some(true)
                              } else {
                                  None
                              }))
    }

    fn help(&mut self) -> Option<UsageToken<'u>> {
        self.s = self.e + 2;
        self.e = self.usage.len() - 1;

        while let Some(_) = self.chars.next() {
            continue;
        }

        Some(UsageToken::Help(&self.usage[self.s..self.e]))
    }

    fn long_arg(&mut self) -> Option<UsageToken<'u>> {
        if self.e != 1 {
            self.e += 1;
        }

        self.s = self.e + 1;

        while let Some(c) = self.chars.next() {
            self.e += 1;
            if c == ' ' || c == '=' || c == '.' {
                break;
            }
        }

        if self.e > self.usage.len() {
            return None;
        } else if self.e == self.usage.len() - 1 {
            return Some(UsageToken::Long(&self.usage[self.s..]));
        }

        Some(UsageToken::Long(&self.usage[self.s..self.e]))
    }

    fn short_arg(&mut self, c: char) -> Option<UsageToken<'u>> {
        // When short is first don't increment e
        if self.e != 1 {
            self.e += 1;
        }
        if !c.is_alphanumeric() {
            return None;
        }
        Some(UsageToken::Short(c))
    }

    fn multiple(&mut self) -> bool {
        self.e += 1;
        let mut mult = false;
        for _ in 0..2 {
            self.e += 1;
            match self.chars.next() {
                // longs consume one '.' so they match '.. ' whereas shorts can
                // match '...'
                Some('.') | Some(' ') => {
                    mult = true;
                }
                _ => {
                    // if there is no help or following space all we can match is '..'
                    if self.e == self.usage.len() - 1 {
                        mult = true;
                    }
                    break;
                }
            }
        }

        mult
    }
}

impl<'u> Iterator for UsageParser<'u> {
    type Item = UsageToken<'u>;

    fn next(&mut self) -> Option<UsageToken<'u>> {
        loop {
            match self.chars.next() {
                Some(c) if c == '[' || c == '<' => {
                    return self.name(c);
                }
                Some('\'') => {
                    return self.help();
                }
                Some('-') => {
                    self.e += 1;
                    match self.chars.next() {
                        Some('-') => {
                            return self.long_arg();
                        }
                        Some(c) => {
                            return self.short_arg(c);
                        }
                        _ => {
                            return None;
                        }
                    }
                }
                Some('.') => {
                    if self.multiple() {
                        return Some(UsageToken::Multiple);
                    }
                }
                Some(' ') | Some('=') | Some(']') | Some('>') | Some('\t') | Some(',') => {
                    self.e += 1;
                    continue;
                }
                None => {
                    return None;
                }
                Some(c) => panic!("Usage parser error, unexpected \
                                  \"{}\" at \"{}\", check from_usage call",
                                  c,
                                  self.usage),
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate polydraw;

use std::usize;

use polydraw::{Application, Renderer, Frame};
use polydraw::draw::RGB;
use polydraw::raster::{Scene, Point, Segment, Circle, EdgeType, Edge, Poly};
use polydraw::geom::number::NumberOps;

const DIV_PER_PIXEL: i64 = 1000;

#[inline]
fn to_px(v: i64) -> i64 {
   v / DIV_PER_PIXEL
}

#[inline]
fn from_px(v: i64) -> i64 {
   v as i64 * DIV_PER_PIXEL
}

struct SceneRenderer {
   index: usize,
}

impl SceneRenderer {
   fn new() -> Self {
      SceneRenderer {
         index: 0
      }
   }

   fn create_scene(&self) -> Scene {
      let points = vec![
         Point::new(0, 0),   // 0
         Point::new(8, 0),   // 1
         Point::new(12, 0),  // 2
         Point::new(12, 4),  // 3
         Point::new(0, 8),   // 4
         Point::new(0, 12),  // 5
         Point::new(4, 12),  // 6
         Point::new(12, 12), // 7
         Point::new(8, 4),   // 8
         Point::new(4, 8),   // 9
      ];

      let segments = vec![
         Segment::new(0, 1), // a 0
         Segment::new(1, 2), // b 1
         Segment::new(0, 4), // c 2
         Segment::new(1, 3), // d 3
         Segment::new(2, 3), // e 4
         Segment::new(3, 7), // f 5
         Segment::new(4, 5), // g 6
         Segment::new(4, 6), // h 7
         Segment::new(5, 6), // i 8
         Segment::new(6, 7), // j 9
      ];

      let circles = vec![
         Circle::new(8, 4),  // 0
         Circle::new(9, 4),  // 1
      ];

      let edges = vec![
         Edge::new(EdgeType::LVT, 2, usize::MAX),
         Edge::new(EdgeType::CTR, 7, 1),
         Edge::new(EdgeType::LHR, 9, usize::MAX),
         Edge::new(EdgeType::LVB, 5, usize::MAX),
         Edge::new(EdgeType::CBL, 3, 0),
         Edge::new(EdgeType::LHL, 0, usize::MAX),
         Edge::new(EdgeType::ABL, 3, 0),
         Edge::new(EdgeType::LVB, 4, usize::MAX),
         Edge::new(EdgeType::LHL, 1, usize::MAX),
         Edge::new(EdgeType::LVT, 6, usize::MAX),
         Edge::new(EdgeType::LHR, 8, usize::MAX),
         Edge::new(EdgeType::ATR, 7, 1),
      ];

      let polys = vec![
         Poly::new(0, 6, 0),
         Poly::new(6, 9, 1),
         Poly::new(9, 12, 2),
      ];

      let colors = vec![
         RGB::new(194, 243, 137),
         RGB::new(154, 222, 76),
         RGB::new(172, 58, 162),
      ];

      Scene {
         points: points,
         segments: segments,
         circles: circles,
         edges: edges,
         polys: polys,
         colors: colors,
      }
   }
}

impl Renderer for SceneRenderer {
   fn render(&mut self, frame: &mut Frame) {
      frame.clear();

      let scene = self.create_scene();

      scene.check_correctness();
   }
}

fn main() {
   let mut renderer = SceneRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Scene")
      .run();
}
<commit_msg>Cleaning up unused variables in the scene sandbox example<commit_after>extern crate polydraw;

use std::usize;

use polydraw::{Application, Renderer, Frame};
use polydraw::draw::RGB;
use polydraw::raster::{Scene, Point, Segment, Circle, EdgeType, Edge, Poly};

struct SceneRenderer;

impl SceneRenderer {
   fn new() -> Self {
      SceneRenderer
   }

   fn create_scene(&self) -> Scene {
      let points = vec![
         Point::new(0, 0),   // 0
         Point::new(8, 0),   // 1
         Point::new(12, 0),  // 2
         Point::new(12, 4),  // 3
         Point::new(0, 8),   // 4
         Point::new(0, 12),  // 5
         Point::new(4, 12),  // 6
         Point::new(12, 12), // 7
         Point::new(8, 4),   // 8
         Point::new(4, 8),   // 9
      ];

      let segments = vec![
         Segment::new(0, 1), // a 0
         Segment::new(1, 2), // b 1
         Segment::new(0, 4), // c 2
         Segment::new(1, 3), // d 3
         Segment::new(2, 3), // e 4
         Segment::new(3, 7), // f 5
         Segment::new(4, 5), // g 6
         Segment::new(4, 6), // h 7
         Segment::new(5, 6), // i 8
         Segment::new(6, 7), // j 9
      ];

      let circles = vec![
         Circle::new(8, 4),  // 0
         Circle::new(9, 4),  // 1
      ];

      let edges = vec![
         Edge::new(EdgeType::LVT, 2, usize::MAX),
         Edge::new(EdgeType::CTR, 7, 1),
         Edge::new(EdgeType::LHR, 9, usize::MAX),
         Edge::new(EdgeType::LVB, 5, usize::MAX),
         Edge::new(EdgeType::CBL, 3, 0),
         Edge::new(EdgeType::LHL, 0, usize::MAX),
         Edge::new(EdgeType::ABL, 3, 0),
         Edge::new(EdgeType::LVB, 4, usize::MAX),
         Edge::new(EdgeType::LHL, 1, usize::MAX),
         Edge::new(EdgeType::LVT, 6, usize::MAX),
         Edge::new(EdgeType::LHR, 8, usize::MAX),
         Edge::new(EdgeType::ATR, 7, 1),
      ];

      let polys = vec![
         Poly::new(0, 6, 0),
         Poly::new(6, 9, 1),
         Poly::new(9, 12, 2),
      ];

      let colors = vec![
         RGB::new(194, 243, 137),
         RGB::new(154, 222, 76),
         RGB::new(172, 58, 162),
      ];

      Scene {
         points: points,
         segments: segments,
         circles: circles,
         edges: edges,
         polys: polys,
         colors: colors,
      }
   }
}

impl Renderer for SceneRenderer {
   fn render(&mut self, frame: &mut Frame) {
      frame.clear();

      let scene = self.create_scene();

      scene.check_correctness();
   }
}

fn main() {
   let mut renderer = SceneRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Scene")
      .run();
}
<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

//! The macros crate contains all useful needed macros.

/// Get the count of macro's arguments.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate tikv;
/// # fn main() {
/// assert_eq!(count_args!(), 0);
/// assert_eq!(count_args!(1), 1);
/// assert_eq!(count_args!(1, 2), 2);
/// assert_eq!(count_args!(1, 2, 3), 3);
/// # }
/// ```
#[macro_export]
macro_rules! count_args {
    () => { 0 };
    ($head:expr $(, $tail:expr)*) => { 1 + count_args!($($tail),*) };
}

/// Initial a `HashMap` with specify key-value pairs.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate tikv;
/// # fn main() {
/// // empty map
/// let m: tikv::util::collections::HashMap<u8, u8> = map!();
/// assert!(m.is_empty());
///
/// // one initial kv pairs.
/// let m = map!("key" => "value");
/// assert_eq!(m.len(), 1);
/// assert_eq!(m["key"], "value");
///
/// // initialize with multiple kv pairs.
/// let m = map!("key1" => "value1", "key2" => "value2");
/// assert_eq!(m.len(), 2);
/// assert_eq!(m["key1"], "value1");
/// assert_eq!(m["key2"], "value2");
/// # }
/// ```
///
/// This macro may be removed once
/// [official implementation](https://github.com/rust-lang/rfcs/issues/542) is provided.
#[macro_export]
macro_rules! map {
    () => {
        {
            $crate::util::collections::HashMap::default()
        }
    };
    ( $( $k:expr => $v:expr ),+ ) => {
        {
            let mut temp_map =
                $crate::util::collections::HashMap::with_capacity_and_hasher(
                    count_args!($(($k, $v)),+),
                    Default::default()
                );
            $(
                temp_map.insert($k, $v);
            )+
            temp_map
        }
    };
}

/// box try will box error first, and then do the same thing as try!.
#[macro_export]
macro_rules! box_try {
    ($expr:expr) => ({
        match $expr {
            Ok(r) => r,
            Err(e) => return Err(box_err!(e)),
        }
    })
}

/// A shortcut to box an error.
#[macro_export]
macro_rules! box_err {
    ($e:expr) => ({
        use std::error::Error;
        let e: Box<Error + Sync + Send> = ($e).into();
        e.into()
    });
    ($f:tt, $($arg:expr),+) => ({
        box_err!(format!($f, $($arg),+))
    });
}

#[allow(doc_markdown)]
/// Recover from panicable closure.
///
/// Please note that this macro assume the closure is able to be forced to implement `UnwindSafe`.
/// Also see https://doc.rust-lang.org/std/panic/struct.AssertUnwindSafe.html
// Maybe we should define a recover macro too.
#[macro_export]
macro_rules! recover_safe {
    ($e:expr) => ({
        use std::panic::{AssertUnwindSafe, catch_unwind};
        use $crate::util::panic_hook;
        panic_hook::mute();
        let res = catch_unwind(AssertUnwindSafe($e));
        panic_hook::unmute();
        res
    })
}

/// Log slow operations with warn!.
macro_rules! slow_log {
    ($t:expr, $($arg:tt)*) => {{
        if $t.is_slow() {
            warn!("{} [takes {:?}]", format_args!($($arg)*), $t.elapsed());
        }
    }}
}

/// make a thread name with additional tag inheriting from current thread.
#[macro_export]
macro_rules! thd_name {
    ($name:expr) => ({
        $crate::util::get_tag_from_thread_name().map(|tag| {
            format!("{}::{}", $name, tag)
        }).unwrap_or_else(|| $name.to_owned())
    });
}

/// Simulating go's defer.
///
/// Please note that, different from go, this defer is bound to scope.
#[macro_export]
macro_rules! defer {
    ($t:expr) => (
        let __ctx = $crate::util::DeferContext::new(|| $t);
    );
}

/// `wait_op!` waits for async operation. It returns `Option<Res>`
/// after the expression get executed.
#[macro_export]
macro_rules! wait_op {
    ($expr:expr) => {
        wait_op!(IMPL $expr, None)
    };
    ($expr:expr, $timeout:expr) => {
        wait_op!(IMPL $expr, Some($timeout))
    };
    (IMPL $expr:expr, $timeout:expr) => {
        {
            use std::sync::mpsc;
            let (tx, rx) = mpsc::channel();
            let cb = box move |res| {
                 // we don't care error actually.
                let _ = tx.send(res);
            };
            $expr(cb);
            match $timeout {
                None => rx.recv().ok(),
                Some(timeout) => rx.recv_timeout(timeout).ok()
            }
        }
    }
}

/// `try_opt` check `Result<Option<T>>`, return early when met `Err` or `Ok(None)`.
#[macro_export]
macro_rules! try_opt {
    ($expr:expr) => ({
        match $expr {
            Err(e) => return Err(e.into()),
            Ok(None) => return Ok(None),
            Ok(Some(res)) => res,
        }
    });
}
<commit_msg>Document defer macro LIFO behavior (#2415)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

//! The macros crate contains all useful needed macros.

/// Get the count of macro's arguments.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate tikv;
/// # fn main() {
/// assert_eq!(count_args!(), 0);
/// assert_eq!(count_args!(1), 1);
/// assert_eq!(count_args!(1, 2), 2);
/// assert_eq!(count_args!(1, 2, 3), 3);
/// # }
/// ```
#[macro_export]
macro_rules! count_args {
    () => { 0 };
    ($head:expr $(, $tail:expr)*) => { 1 + count_args!($($tail),*) };
}

/// Initial a `HashMap` with specify key-value pairs.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate tikv;
/// # fn main() {
/// // empty map
/// let m: tikv::util::collections::HashMap<u8, u8> = map!();
/// assert!(m.is_empty());
///
/// // one initial kv pairs.
/// let m = map!("key" => "value");
/// assert_eq!(m.len(), 1);
/// assert_eq!(m["key"], "value");
///
/// // initialize with multiple kv pairs.
/// let m = map!("key1" => "value1", "key2" => "value2");
/// assert_eq!(m.len(), 2);
/// assert_eq!(m["key1"], "value1");
/// assert_eq!(m["key2"], "value2");
/// # }
/// ```
///
/// This macro may be removed once
/// [official implementation](https://github.com/rust-lang/rfcs/issues/542) is provided.
#[macro_export]
macro_rules! map {
    () => {
        {
            $crate::util::collections::HashMap::default()
        }
    };
    ( $( $k:expr => $v:expr ),+ ) => {
        {
            let mut temp_map =
                $crate::util::collections::HashMap::with_capacity_and_hasher(
                    count_args!($(($k, $v)),+),
                    Default::default()
                );
            $(
                temp_map.insert($k, $v);
            )+
            temp_map
        }
    };
}

/// box try will box error first, and then do the same thing as try!.
#[macro_export]
macro_rules! box_try {
    ($expr:expr) => ({
        match $expr {
            Ok(r) => r,
            Err(e) => return Err(box_err!(e)),
        }
    })
}

/// A shortcut to box an error.
#[macro_export]
macro_rules! box_err {
    ($e:expr) => ({
        use std::error::Error;
        let e: Box<Error + Sync + Send> = ($e).into();
        e.into()
    });
    ($f:tt, $($arg:expr),+) => ({
        box_err!(format!($f, $($arg),+))
    });
}

#[allow(doc_markdown)]
/// Recover from panicable closure.
///
/// Please note that this macro assume the closure is able to be forced to implement `UnwindSafe`.
/// Also see https://doc.rust-lang.org/std/panic/struct.AssertUnwindSafe.html
// Maybe we should define a recover macro too.
#[macro_export]
macro_rules! recover_safe {
    ($e:expr) => ({
        use std::panic::{AssertUnwindSafe, catch_unwind};
        use $crate::util::panic_hook;
        panic_hook::mute();
        let res = catch_unwind(AssertUnwindSafe($e));
        panic_hook::unmute();
        res
    })
}

/// Log slow operations with warn!.
macro_rules! slow_log {
    ($t:expr, $($arg:tt)*) => {{
        if $t.is_slow() {
            warn!("{} [takes {:?}]", format_args!($($arg)*), $t.elapsed());
        }
    }}
}

/// make a thread name with additional tag inheriting from current thread.
#[macro_export]
macro_rules! thd_name {
    ($name:expr) => ({
        $crate::util::get_tag_from_thread_name().map(|tag| {
            format!("{}::{}", $name, tag)
        }).unwrap_or_else(|| $name.to_owned())
    });
}

/// Simulating go's defer.
///
/// Please note that, different from go, this defer is bound to scope.
/// When exiting the scope, its deferred calls are executed in last-in-first-out order.
#[macro_export]
macro_rules! defer {
    ($t:expr) => (
        let __ctx = $crate::util::DeferContext::new(|| $t);
    );
}

/// `wait_op!` waits for async operation. It returns `Option<Res>`
/// after the expression get executed.
#[macro_export]
macro_rules! wait_op {
    ($expr:expr) => {
        wait_op!(IMPL $expr, None)
    };
    ($expr:expr, $timeout:expr) => {
        wait_op!(IMPL $expr, Some($timeout))
    };
    (IMPL $expr:expr, $timeout:expr) => {
        {
            use std::sync::mpsc;
            let (tx, rx) = mpsc::channel();
            let cb = box move |res| {
                 // we don't care error actually.
                let _ = tx.send(res);
            };
            $expr(cb);
            match $timeout {
                None => rx.recv().ok(),
                Some(timeout) => rx.recv_timeout(timeout).ok()
            }
        }
    }
}

/// `try_opt` check `Result<Option<T>>`, return early when met `Err` or `Ok(None)`.
#[macro_export]
macro_rules! try_opt {
    ($expr:expr) => ({
        match $expr {
            Err(e) => return Err(e.into()),
            Ok(None) => return Ok(None),
            Ok(Some(res)) => res,
        }
    });
}
<|endoftext|>


<commit_before>//! The Credentials provider to read from a task's IAM Role.

use std::error::Error;
use futures::{Async, Future, Poll};
use futures::future::err;
use hyper::{Client, Uri, Request, Method};
//use hyper::error::UriError;
use hyper::header::Authorization;
use hyper::client::HttpConnector;
use tokio_core::reactor::Handle;

use {AwsCredentials, CredentialsError, ProvideAwsCredentials,
     make_request, parse_credentials_from_aws_service, non_empty_env_var};

// The following constants are documented in AWS' ECS developers guide,
// see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html.
const AWS_CREDENTIALS_PROVIDER_IP: &'static str = "169.254.170.2";
const AWS_CONTAINER_CREDENTIALS_RELATIVE_URI: &str = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI";
// I have not yet found any official documentation from AWS concerning the following two
// environment variables, but they are used by the Java, Go, JavaScript and the Python SDKs.
const AWS_CONTAINER_CREDENTIALS_FULL_URI: &str = "AWS_CONTAINER_CREDENTIALS_FULL_URI";
const AWS_CONTAINER_AUTHORIZATION_TOKEN: &str = "AWS_CONTAINER_AUTHORIZATION_TOKEN";

/// Provides AWS credentials from a task's IAM role.
///
/// As described in Amazon's
/// [ECS developers guide](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html),
/// Containers started as part of Tasks using IAM Roles for Tasks will be provided with a relative
/// URL stored in the environment variable ```AWS_CONTAINER_CREDENTIALS_RELATIVE_URI```, which will
/// be used to obtain the AWS credentials. If that environment variable is not set, rusoto will use
/// the URL set in environment variable ```AWS_CONTAINER_CREDENTIALS_FULL_URI``` to obtain AWS
/// credentials and will (optionally) also set the ```Authorization``` header to the value of
/// environment variable ```AWS_CONTAINER_AUTHORIZATION_TOKEN```.
///
#[derive(Clone, Debug)]
pub struct ContainerProvider {
    client: Client<HttpConnector>
}

impl ContainerProvider {
    /// Create a new provider with the given handle.
    pub fn new(handle: &Handle) -> Self {
        let client = Client::configure().build(handle);
        ContainerProvider { client: client }
    }
}

/// Future returned from `ContainerProvider`.
pub struct ContainerProviderFuture {
    inner: Box<Future<Item=String, Error=CredentialsError>>
}

impl Future for ContainerProviderFuture {
    type Item = AwsCredentials;
    type Error = CredentialsError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let resp = try_ready!(self.inner.poll());
        let creds = parse_credentials_from_aws_service(&resp)?;
        Ok(Async::Ready(creds))
    }
}

impl ProvideAwsCredentials for ContainerProvider {
    type Future = ContainerProviderFuture;

    fn credentials(&self) -> Self::Future {
        let inner = match credentials_from_container(&self.client) {
            Ok(future) => future,
            Err(e) => Box::new(err(e))
        };
        ContainerProviderFuture { inner: inner }
    }
}

/// Grabs the Credentials from the AWS Container Credentials Provider. (169.254.170.2).
fn credentials_from_container(client: &Client<HttpConnector>) -> Result<Box<Future<Item=String, Error=CredentialsError>>, CredentialsError> {
    Ok(make_request(client, request_from_env_vars()?))
}

fn request_from_env_vars() -> Result<Request, CredentialsError> {
    let relative_uri = non_empty_env_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI).map(
        |path| format!("http://{}{}", AWS_CREDENTIALS_PROVIDER_IP, path)
    );
    match relative_uri {
        Some(ref uri) => new_request(uri, AWS_CONTAINER_CREDENTIALS_RELATIVE_URI),
        None => match non_empty_env_var(AWS_CONTAINER_CREDENTIALS_FULL_URI) {
            Some(ref uri) => {
                let mut request = new_request(uri, AWS_CONTAINER_CREDENTIALS_FULL_URI)?;
                let token = non_empty_env_var(AWS_CONTAINER_AUTHORIZATION_TOKEN);
                token.map(|t| request.headers_mut().set(Authorization(t)));
                Ok(request)
            },
            None => Err(CredentialsError::new(
                format!("Neither environment variable '{}' nor '{}' is set", AWS_CONTAINER_CREDENTIALS_FULL_URI, AWS_CONTAINER_CREDENTIALS_RELATIVE_URI),
            ))
        }
    }
}

fn new_request(uri: &str, env_var_name: &str) -> Result<Request, CredentialsError> {
    uri.parse::<Uri>().map(
            |uri| Request::new(Method::Get, uri)
        ).or_else(|error| Err(
             CredentialsError::new(
                 format!("Error while parsing URI '{}' derived from environment variable '{}': {}",
                         uri, env_var_name, error.description())
             )
        )
    )
}

#[cfg(test)]
mod tests {
    use std::env;
    use std::sync::{Mutex, MutexGuard};
    use hyper::header::Authorization;
    use hyper::header::Bearer;
    use super::*;

    // cargo runs tests in parallel, which leads to race conditions when changing
    // environment variables. Therefore we use a global mutex for all tests which
    // rely on environment variables.
    lazy_static! {
        static ref ENV_MUTEX: Mutex<()> = Mutex::new(());
    }

    // As failed (panic) tests will poisen the global mutex, we use a helper which
    // recovers from poisoned mutex.
    fn lock<'a, T>(mutex: &'a Mutex<T>) -> MutexGuard<'a, T> {
        match mutex.lock() {
            Ok(guard) => guard,
            Err(poisoned) => poisoned.into_inner(),
        }
    }

    #[test]
    fn request_from_relative_uri() {
        let path = "/xxx";
        let _guard = lock(&ENV_MUTEX);
        env::set_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, path);
        env::set_var(AWS_CONTAINER_CREDENTIALS_FULL_URI, "dummy");
        env::set_var(AWS_CONTAINER_AUTHORIZATION_TOKEN, "dummy");
        let result = request_from_env_vars();
        env::remove_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI);
        env::remove_var(AWS_CONTAINER_CREDENTIALS_FULL_URI);
        env::remove_var(AWS_CONTAINER_AUTHORIZATION_TOKEN);
        assert!(result.is_ok());
        let request = result.ok().unwrap();
        assert_eq!(request.uri().path(), path);
        assert_eq!(request.headers().has::<Authorization<Bearer>>(), false);
    }

    #[test]
    fn error_from_missing_env_vars() {
        let _guard = lock(&ENV_MUTEX);
        env::remove_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI);
        env::remove_var(AWS_CONTAINER_CREDENTIALS_FULL_URI);
        let result = request_from_env_vars();
        assert!(result.is_err());
    }

    #[test]
    fn error_from_empty_env_vars() {
        let _guard = lock(&ENV_MUTEX);
        env::set_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, "");
        env::set_var(AWS_CONTAINER_CREDENTIALS_FULL_URI, "");
        env::set_var(AWS_CONTAINER_AUTHORIZATION_TOKEN, "");
        let result = request_from_env_vars();
        env::remove_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI);
        env::remove_var(AWS_CONTAINER_CREDENTIALS_FULL_URI);
        env::remove_var(AWS_CONTAINER_AUTHORIZATION_TOKEN);
        assert!(result.is_err());
    }

    #[test]
    fn request_from_full_uri_with_token() {
        let url = "http://localhost/xxx";
        let _guard = lock(&ENV_MUTEX);
        env::remove_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI);
        env::set_var(AWS_CONTAINER_CREDENTIALS_FULL_URI, url);
        env::set_var(AWS_CONTAINER_AUTHORIZATION_TOKEN, "dummy");
        let result = request_from_env_vars();
        env::remove_var(AWS_CONTAINER_CREDENTIALS_FULL_URI);
        env::remove_var(AWS_CONTAINER_AUTHORIZATION_TOKEN);
        assert!(result.is_ok());
        let request = result.ok().unwrap();
        assert_eq!(request.uri().to_string(), url);
        assert_eq!(request.headers().has::<Authorization<Bearer>>(), true);
    }

    #[test]
    fn request_from_full_uri_without_token() {
        let url = "http://localhost/xxx";
        let _guard = lock(&ENV_MUTEX);
        env::remove_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI);
        env::set_var(AWS_CONTAINER_CREDENTIALS_FULL_URI, url);
        env::remove_var(AWS_CONTAINER_AUTHORIZATION_TOKEN);
        let result = request_from_env_vars();
        env::remove_var(AWS_CONTAINER_CREDENTIALS_FULL_URI);
        assert!(result.is_ok());
        let request = result.ok().unwrap();
        assert_eq!(request.uri().to_string(), url);
        assert_eq!(request.headers().has::<Authorization<Bearer>>(), false);
    }

    #[test]
    fn request_from_full_uri_with_empty_token() {
        let url = "http://localhost/xxx";
        let _guard = lock(&ENV_MUTEX);
        env::remove_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI);
        env::set_var(AWS_CONTAINER_CREDENTIALS_FULL_URI, url);
        env::set_var(AWS_CONTAINER_AUTHORIZATION_TOKEN, "");
        let result = request_from_env_vars();
        env::remove_var(AWS_CONTAINER_CREDENTIALS_FULL_URI);
        env::remove_var(AWS_CONTAINER_AUTHORIZATION_TOKEN);
        assert!(result.is_ok());
        let request = result.ok().unwrap();
        assert_eq!(request.uri().to_string(), url);
        assert_eq!(request.headers().has::<Authorization<Bearer>>(), false);
    }
}
<commit_msg>Remove useless line<commit_after>//! The Credentials provider to read from a task's IAM Role.

use std::error::Error;
use futures::{Async, Future, Poll};
use futures::future::err;
use hyper::{Client, Uri, Request, Method};
use hyper::header::Authorization;
use hyper::client::HttpConnector;
use tokio_core::reactor::Handle;

use {AwsCredentials, CredentialsError, ProvideAwsCredentials,
     make_request, parse_credentials_from_aws_service, non_empty_env_var};

// The following constants are documented in AWS' ECS developers guide,
// see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html.
const AWS_CREDENTIALS_PROVIDER_IP: &'static str = "169.254.170.2";
const AWS_CONTAINER_CREDENTIALS_RELATIVE_URI: &str = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI";
// I have not yet found any official documentation from AWS concerning the following two
// environment variables, but they are used by the Java, Go, JavaScript and the Python SDKs.
const AWS_CONTAINER_CREDENTIALS_FULL_URI: &str = "AWS_CONTAINER_CREDENTIALS_FULL_URI";
const AWS_CONTAINER_AUTHORIZATION_TOKEN: &str = "AWS_CONTAINER_AUTHORIZATION_TOKEN";

/// Provides AWS credentials from a task's IAM role.
///
/// As described in Amazon's
/// [ECS developers guide](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html),
/// Containers started as part of Tasks using IAM Roles for Tasks will be provided with a relative
/// URL stored in the environment variable ```AWS_CONTAINER_CREDENTIALS_RELATIVE_URI```, which will
/// be used to obtain the AWS credentials. If that environment variable is not set, rusoto will use
/// the URL set in environment variable ```AWS_CONTAINER_CREDENTIALS_FULL_URI``` to obtain AWS
/// credentials and will (optionally) also set the ```Authorization``` header to the value of
/// environment variable ```AWS_CONTAINER_AUTHORIZATION_TOKEN```.
///
#[derive(Clone, Debug)]
pub struct ContainerProvider {
    client: Client<HttpConnector>
}

impl ContainerProvider {
    /// Create a new provider with the given handle.
    pub fn new(handle: &Handle) -> Self {
        let client = Client::configure().build(handle);
        ContainerProvider { client: client }
    }
}

/// Future returned from `ContainerProvider`.
pub struct ContainerProviderFuture {
    inner: Box<Future<Item=String, Error=CredentialsError>>
}

impl Future for ContainerProviderFuture {
    type Item = AwsCredentials;
    type Error = CredentialsError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let resp = try_ready!(self.inner.poll());
        let creds = parse_credentials_from_aws_service(&resp)?;
        Ok(Async::Ready(creds))
    }
}

impl ProvideAwsCredentials for ContainerProvider {
    type Future = ContainerProviderFuture;

    fn credentials(&self) -> Self::Future {
        let inner = match credentials_from_container(&self.client) {
            Ok(future) => future,
            Err(e) => Box::new(err(e))
        };
        ContainerProviderFuture { inner: inner }
    }
}

/// Grabs the Credentials from the AWS Container Credentials Provider. (169.254.170.2).
fn credentials_from_container(client: &Client<HttpConnector>) -> Result<Box<Future<Item=String, Error=CredentialsError>>, CredentialsError> {
    Ok(make_request(client, request_from_env_vars()?))
}

fn request_from_env_vars() -> Result<Request, CredentialsError> {
    let relative_uri = non_empty_env_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI).map(
        |path| format!("http://{}{}", AWS_CREDENTIALS_PROVIDER_IP, path)
    );
    match relative_uri {
        Some(ref uri) => new_request(uri, AWS_CONTAINER_CREDENTIALS_RELATIVE_URI),
        None => match non_empty_env_var(AWS_CONTAINER_CREDENTIALS_FULL_URI) {
            Some(ref uri) => {
                let mut request = new_request(uri, AWS_CONTAINER_CREDENTIALS_FULL_URI)?;
                let token = non_empty_env_var(AWS_CONTAINER_AUTHORIZATION_TOKEN);
                token.map(|t| request.headers_mut().set(Authorization(t)));
                Ok(request)
            },
            None => Err(CredentialsError::new(
                format!("Neither environment variable '{}' nor '{}' is set", AWS_CONTAINER_CREDENTIALS_FULL_URI, AWS_CONTAINER_CREDENTIALS_RELATIVE_URI),
            ))
        }
    }
}

fn new_request(uri: &str, env_var_name: &str) -> Result<Request, CredentialsError> {
    uri.parse::<Uri>().map(
            |uri| Request::new(Method::Get, uri)
        ).or_else(|error| Err(
             CredentialsError::new(
                 format!("Error while parsing URI '{}' derived from environment variable '{}': {}",
                         uri, env_var_name, error.description())
             )
        )
    )
}

#[cfg(test)]
mod tests {
    use std::env;
    use std::sync::{Mutex, MutexGuard};
    use hyper::header::Authorization;
    use hyper::header::Bearer;
    use super::*;

    // cargo runs tests in parallel, which leads to race conditions when changing
    // environment variables. Therefore we use a global mutex for all tests which
    // rely on environment variables.
    lazy_static! {
        static ref ENV_MUTEX: Mutex<()> = Mutex::new(());
    }

    // As failed (panic) tests will poisen the global mutex, we use a helper which
    // recovers from poisoned mutex.
    fn lock<'a, T>(mutex: &'a Mutex<T>) -> MutexGuard<'a, T> {
        match mutex.lock() {
            Ok(guard) => guard,
            Err(poisoned) => poisoned.into_inner(),
        }
    }

    #[test]
    fn request_from_relative_uri() {
        let path = "/xxx";
        let _guard = lock(&ENV_MUTEX);
        env::set_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, path);
        env::set_var(AWS_CONTAINER_CREDENTIALS_FULL_URI, "dummy");
        env::set_var(AWS_CONTAINER_AUTHORIZATION_TOKEN, "dummy");
        let result = request_from_env_vars();
        env::remove_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI);
        env::remove_var(AWS_CONTAINER_CREDENTIALS_FULL_URI);
        env::remove_var(AWS_CONTAINER_AUTHORIZATION_TOKEN);
        assert!(result.is_ok());
        let request = result.ok().unwrap();
        assert_eq!(request.uri().path(), path);
        assert_eq!(request.headers().has::<Authorization<Bearer>>(), false);
    }

    #[test]
    fn error_from_missing_env_vars() {
        let _guard = lock(&ENV_MUTEX);
        env::remove_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI);
        env::remove_var(AWS_CONTAINER_CREDENTIALS_FULL_URI);
        let result = request_from_env_vars();
        assert!(result.is_err());
    }

    #[test]
    fn error_from_empty_env_vars() {
        let _guard = lock(&ENV_MUTEX);
        env::set_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, "");
        env::set_var(AWS_CONTAINER_CREDENTIALS_FULL_URI, "");
        env::set_var(AWS_CONTAINER_AUTHORIZATION_TOKEN, "");
        let result = request_from_env_vars();
        env::remove_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI);
        env::remove_var(AWS_CONTAINER_CREDENTIALS_FULL_URI);
        env::remove_var(AWS_CONTAINER_AUTHORIZATION_TOKEN);
        assert!(result.is_err());
    }

    #[test]
    fn request_from_full_uri_with_token() {
        let url = "http://localhost/xxx";
        let _guard = lock(&ENV_MUTEX);
        env::remove_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI);
        env::set_var(AWS_CONTAINER_CREDENTIALS_FULL_URI, url);
        env::set_var(AWS_CONTAINER_AUTHORIZATION_TOKEN, "dummy");
        let result = request_from_env_vars();
        env::remove_var(AWS_CONTAINER_CREDENTIALS_FULL_URI);
        env::remove_var(AWS_CONTAINER_AUTHORIZATION_TOKEN);
        assert!(result.is_ok());
        let request = result.ok().unwrap();
        assert_eq!(request.uri().to_string(), url);
        assert_eq!(request.headers().has::<Authorization<Bearer>>(), true);
    }

    #[test]
    fn request_from_full_uri_without_token() {
        let url = "http://localhost/xxx";
        let _guard = lock(&ENV_MUTEX);
        env::remove_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI);
        env::set_var(AWS_CONTAINER_CREDENTIALS_FULL_URI, url);
        env::remove_var(AWS_CONTAINER_AUTHORIZATION_TOKEN);
        let result = request_from_env_vars();
        env::remove_var(AWS_CONTAINER_CREDENTIALS_FULL_URI);
        assert!(result.is_ok());
        let request = result.ok().unwrap();
        assert_eq!(request.uri().to_string(), url);
        assert_eq!(request.headers().has::<Authorization<Bearer>>(), false);
    }

    #[test]
    fn request_from_full_uri_with_empty_token() {
        let url = "http://localhost/xxx";
        let _guard = lock(&ENV_MUTEX);
        env::remove_var(AWS_CONTAINER_CREDENTIALS_RELATIVE_URI);
        env::set_var(AWS_CONTAINER_CREDENTIALS_FULL_URI, url);
        env::set_var(AWS_CONTAINER_AUTHORIZATION_TOKEN, "");
        let result = request_from_env_vars();
        env::remove_var(AWS_CONTAINER_CREDENTIALS_FULL_URI);
        env::remove_var(AWS_CONTAINER_AUTHORIZATION_TOKEN);
        assert!(result.is_ok());
        let request = result.ok().unwrap();
        assert_eq!(request.uri().to_string(), url);
        assert_eq!(request.headers().has::<Authorization<Bearer>>(), false);
    }
}
<|endoftext|>


<commit_before>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::{self, IResult};
use metadata::{Metadata, metadata_parser};

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T, E>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, E>;
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

// Bit shifted version for two to the power of a given exponent.
#[inline]
pub fn power_of_two(exponent: u32) -> u32 {
  1 << exponent
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

#[inline]
fn header_parser(input: &[u8]) -> IResult<&[u8], &[u8], ErrorKind> {
  tag!(input, "fLaC").map_err(to_custom_error!(HeaderParser))
}

#[inline]
fn metadata_parser_(input: &[u8]) -> IResult<&[u8], Metadata, ErrorKind> {
  metadata_parser(input).map_err(to_custom_error!(Unknown))
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata> {
  let mut slice = input;
  let error     = nom::Err::Code(nom::ErrorKind::Custom(10));

  if *state == ParserState::Header {
    let (i, _) = try_parse!(slice, tag!("fLaC"));

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  match *state {
    ParserState::StreamInfo => {
      let (i, block) = try_parse!(slice, metadata_parser);

      if block.is_stream_info() {
        *state = ParserState::Metadata;

        IResult::Done(i, block)
      } else {
        IResult::Error(error)
      }
    }
    ParserState::Metadata   => metadata_parser(slice),
    _                       => IResult::Error(error),
  }
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> bool
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state    = ParserState::Header;
  let mut is_error = false;

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last();

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(_)                   => {
        is_error = true;

        break;
      }
    }
  }

  is_error
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }

  #[test]
  fn test_power_of_two() {
    assert_eq!(power_of_two(0), 1);
    assert_eq!(power_of_two(1), 2);
    assert_eq!(power_of_two(2), 4);
    assert_eq!(power_of_two(10), 1024);
    assert_eq!(power_of_two(31), 2147483648);
  }
}
<commit_msg>Change the metadata parser return `ErrorKind`<commit_after>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::{self, IResult};
use metadata::{Metadata, metadata_parser};

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T, E>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, E>;
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

// Bit shifted version for two to the power of a given exponent.
#[inline]
pub fn power_of_two(exponent: u32) -> u32 {
  1 << exponent
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

#[inline]
fn header_parser(input: &[u8]) -> IResult<&[u8], &[u8], ErrorKind> {
  tag!(input, "fLaC").map_err(to_custom_error!(HeaderParser))
}

#[inline]
fn metadata_parser_(input: &[u8]) -> IResult<&[u8], Metadata, ErrorKind> {
  metadata_parser(input).map_err(to_custom_error!(Unknown))
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata, ErrorKind> {
  let mut slice = input;
  let error     = nom::Err::Code(nom::ErrorKind::Custom(ErrorKind::Unknown));

  if *state == ParserState::Header {
    let (i, _) = try_parse!(slice, header_parser);

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  match *state {
    ParserState::StreamInfo => {
      let (i, block) = try_parse!(slice, metadata_parser_);

      if block.is_stream_info() {
        *state = ParserState::Metadata;

        IResult::Done(i, block)
      } else {
        IResult::Error(error)
      }
    }
    ParserState::Metadata   => metadata_parser_(slice),
    _                       => IResult::Error(error),
  }
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> bool
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state    = ParserState::Header;
  let mut is_error = false;

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last();

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(_)                   => {
        is_error = true;

        break;
      }
    }
  }

  is_error
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }

  #[test]
  fn test_power_of_two() {
    assert_eq!(power_of_two(0), 1);
    assert_eq!(power_of_two(1), 2);
    assert_eq!(power_of_two(2), 4);
    assert_eq!(power_of_two(10), 1024);
    assert_eq!(power_of_two(31), 2147483648);
  }
}
<|endoftext|>


<commit_before>use crate::grammar::ast::{BinaryExpression, BinaryOp, Expression};
use crate::grammar::model::{Fragment, HasFragment};
use crate::grammar::parsers::expression::binary_expression::operators::{
    Associativity, OperatorInfo,
};
use crate::grammar::parsers::expression::ToExpression;
use crate::grammar::parsers::whitespace::token_delimiter;
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::combinator::{map, value};
use nom::error::ErrorKind;
use nom::sequence::delimited;
use nom::Err::Error;
use nom::IResult;

fn binary_operator<'s>(input: Fragment<'s>) -> IResult<Fragment<'s>, OperatorInfo> {
    use BinaryOp::*;
    delimited(
        token_delimiter,
        map(
            alt((
                value(OrOr, tag("||")),
                value(AndAnd, tag("&&")),
                value(Or, tag("|")),
                value(Xor, tag("^")),
                value(And, tag("&")),
                value(EqEq, tag("==")),
                value(NotEq, tag("!=")),
                value(Le, tag("<=")),
                value(Ge, tag(">=")),
                value(Lt, tag("<")),
                value(Gt, tag(">")),
                value(DotDot, tag("..")),
                value(Add, tag("+")),
                value(Sub, tag("-")),
                value(Mul, tag("*")),
                value(Div, tag("/")),
                value(Mod, tag("%")),
            )),
            BinaryOp::get_info,
        ),
        token_delimiter,
    )(input)
}

fn build_binary_expr<'s>(a: Expression<'s>, op: OperatorInfo, b: Expression<'s>) -> Expression<'s> {
    BinaryExpression::new(
        Fragment::merge(a.get_fragment(), b.get_fragment()).expect("Fragments must be contiguous"),
        a,
        op.id,
        b,
    )
    .create_expr()
}

/// Shunting yard algorithm for structuring binary expressions. Takes
pub fn shunting_yard<'s>(input: Fragment<'s>) -> IResult<Fragment<'s>, BinaryExpression<'s>> {
    let mut exprs = Vec::new();
    let mut ops = Vec::<OperatorInfo>::new();
    // expose remaining input at top-level
    let mut rem = input;
    while let Ok((rem1, operand)) = BinaryExpression::primary(rem) {
        rem = rem1;
        exprs.push(operand);
        if let Ok((rem1, operator)) = binary_operator(rem1) {
            rem = rem1;
            // shunt operators of greater precedence over
            while let Some(top) = ops.pop() {
                use Associativity::Left;
                if top.prec > operator.prec || (top.prec == operator.prec && operator.assoc == Left)
                {
                    // build BinaryExpression and push onto exprs
                    let b = exprs.pop().expect("(b1) exprs stack must be len >= 2");
                    let a = exprs.pop().expect("(a1) exprs stack must be len >= 2");
                    exprs.push(build_binary_expr(a, top, b));
                } else {
                    // repush popped operator, not shunting
                    ops.push(top);
                    break;
                }
            }
            ops.push(operator);
        } else {
            // no operator, stop parsing
            break;
        }
    }
    // shunt over remaining operators
    while let Some(op) = ops.pop() {
        let b = exprs.pop().expect("(b2) exprs stack must be len >= 2");
        let a = exprs.pop().expect("(a2) exprs stack must be len >= 2");
        exprs.push(build_binary_expr(a, op, b));
    }
    if let Some(Expression::BinaryExpression(expr)) = exprs.pop() {
        Ok((rem, expr))
    } else {
        Err(Error((input, ErrorKind::SeparatedNonEmptyList)))
    }
}
<commit_msg>Fix shunting_yard consuming too much<commit_after>use crate::grammar::ast::{BinaryExpression, BinaryOp, Expression};
use crate::grammar::model::{Fragment, HasFragment};
use crate::grammar::parsers::expression::binary_expression::operators::{
    Associativity, OperatorInfo,
};
use crate::grammar::parsers::expression::ToExpression;
use crate::grammar::parsers::whitespace::token_delimiter;
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::combinator::{map, value};
use nom::error::ErrorKind;
use nom::sequence::delimited;
use nom::Err::Error;
use nom::IResult;

fn binary_operator<'s>(input: Fragment<'s>) -> IResult<Fragment<'s>, OperatorInfo> {
    use BinaryOp::*;
    delimited(
        token_delimiter,
        map(
            alt((
                value(OrOr, tag("||")),
                value(AndAnd, tag("&&")),
                value(Or, tag("|")),
                value(Xor, tag("^")),
                value(And, tag("&")),
                value(EqEq, tag("==")),
                value(NotEq, tag("!=")),
                value(Le, tag("<=")),
                value(Ge, tag(">=")),
                value(Lt, tag("<")),
                value(Gt, tag(">")),
                value(DotDot, tag("..")),
                value(Add, tag("+")),
                value(Sub, tag("-")),
                value(Mul, tag("*")),
                value(Div, tag("/")),
                value(Mod, tag("%")),
            )),
            BinaryOp::get_info,
        ),
        token_delimiter,
    )(input)
}

fn build_binary_expr<'s>(a: Expression<'s>, op: OperatorInfo, b: Expression<'s>) -> Expression<'s> {
    BinaryExpression::new(
        Fragment::merge(a.get_fragment(), b.get_fragment()).expect("Fragments must be contiguous"),
        a,
        op.id,
        b,
    )
    .create_expr()
}

/// Shunting yard algorithm for structuring binary expressions. Takes
pub fn shunting_yard<'s>(input: Fragment<'s>) -> IResult<Fragment<'s>, BinaryExpression<'s>> {
    let mut exprs = Vec::new();
    let mut ops = Vec::<OperatorInfo>::new();
    // expose remaining input at top-level
    let mut rem = input;
    // parse the first operand
    if let Ok((rem1, operand)) = BinaryExpression::primary(rem) {
        rem = rem1;
        exprs.push(operand);
        // parse the operator chain
        while let Ok((rem1, operator)) = binary_operator(rem) {
            // shunt operators of greater precedence over
            while let Some(top) = ops.pop() {
                use Associativity::Left;
                if top.prec > operator.prec || (top.prec == operator.prec && operator.assoc == Left)
                {
                    // build BinaryExpression and push onto exprs
                    let b = exprs.pop().expect("(b1) exprs stack must be len >= 2");
                    let a = exprs.pop().expect("(a1) exprs stack must be len >= 2");
                    exprs.push(build_binary_expr(a, top, b));
                } else {
                    // repush popped operator, not shunting
                    ops.push(top);
                    break;
                }
            }
            if let Ok((rem1, operand)) = BinaryExpression::primary(rem1) {
                // commit consuming the source of (operator + second operand)
                rem = rem1;
                ops.push(operator);
                exprs.push(operand);
            } else {
                // don't comsume the source of (operator)
                break;
            }
        }
    }
    // shunt over remaining operators
    while let Some(op) = ops.pop() {
        let b = exprs.pop().expect("(b2) exprs stack must be len >= 2");
        let a = exprs.pop().expect("(a2) exprs stack must be len >= 2");
        exprs.push(build_binary_expr(a, op, b));
    }
    if let Some(Expression::BinaryExpression(expr)) = exprs.pop() {
        Ok((rem, expr))
    } else {
        Err(Error((input, ErrorKind::SeparatedNonEmptyList)))
    }
}
<|endoftext|>