<commit_before>use error;
use reqwest;
use reqwest::header;
use serde_json;
use serde_urlencoded;
use std::env;
use std::fmt;
use std::io::Read;

const API_BASE_PATH: &str = "http://proxer.me/api/v1/";

/// Client that holds the api key and sends requests
#[derive(Debug, Clone)]
pub struct Client {
	api_key: String,
	base_uri: String,
	user_agent: String,
}

#[allow(unused)]
impl Client {
	/// Create a new api client with a given api key
	pub fn new(api_key: String) -> Self
	{
		let crates_name = env::var("CARGO_PKG_NAME").unwrap_or("unknown".to_string());

		let crates_version = &env::var("CARGO_PKG_VERSION").unwrap_or("unknown".to_string());

		let ua = format!("libproxer-rust({}/v{})", crates_name, crates_version);

		Self {
			api_key: api_key,
			base_uri: API_BASE_PATH.to_string(),
			user_agent: ua,
		}
	}

	/// load api key from an environment variable
	pub fn with_env_key(env_key: &str) -> Option<Client>
	{
		match env::var_os(env_key)
		{
			Some(r) => Some(Client::new(r.into_string().unwrap())),
			None => None,
		}
	}

	/// execute a request that satisfies [`Endpoint`](../trait.Endpoint.html)
	pub fn execute<T: super::Endpoint + Clone + fmt::Debug>(
		&self,
		mut endpoint: T,
	) -> Result<T::ResponseType, error::Error>
	{

		let uristring = self.base_uri.to_string() + T::URL;

		header!{(ProxerApiKey, "Proxer-Api-Key") => [String]}

		let mut headers = reqwest::header::Headers::new();

		headers.set(header::UserAgent::new(self.user_agent.to_string()));
		headers.set(header::Host::new("proxer.me", None));
		headers.set(header::ContentType::form_url_encoded());
		headers.set(ProxerApiKey(self.api_key.clone()));

		let mut http_req = reqwest::Request::new(reqwest::Method::Post, uristring.parse().unwrap());

		// add our headers to the request
		http_req.headers_mut().extend(headers.iter());

		match serde_urlencoded::to_string(endpoint.clone())
		{
			Ok(body) => {
				debug!("post data: {}", body);
				*http_req.body_mut() = Some(body.into());
			}
			Err(err) => panic!("can't serialize form parameters"),
		}

		let client = reqwest::Client::new();

		let response = client.execute(http_req);

		// This section needs some rewriting. maybe... later
		match response
		{
			Err(e) => return Err(error::Error::Http),
			Ok(mut res) => {
				let mut json_string = String::new();
				res.read_to_string(&mut json_string);

				// println!("{}", json_string);
				//
				// let value: Value = serde_json::from_str(&json_string).unwrap();
				// println!("{:#?}", value);

				match serde_json::from_str::<ApiResponse<T::ResponseType>>(&json_string)
				{
					Err(e) => return Err(error::Error::Json(e)),
					Ok(r) => {
						if r.error != 0 {
							Err(error::Error::Api(error::api::Api::new(r.code.unwrap(), r.message)))
						}
						else {
							Ok(r.data.unwrap())
						}
					}
				}
			}
		}
	}
}

/// responses are parsed into ApiRequest
#[derive(Debug, Clone, Deserialize)]
pub struct ApiResponse<T> {
	/// api error
	pub error: i64,
	/// api message
	pub message: String,
	/// actual data
	pub data: Option<T>,
	/// optional error code
	/// in case of an error this contains the error code
	pub code: Option<i64>,
}
<commit_msg>remove unnecessary comment<commit_after>use error;
use reqwest;
use reqwest::header;
use serde_json;
use serde_urlencoded;
use std::env;
use std::fmt;
use std::io::Read;

const API_BASE_PATH: &str = "http://proxer.me/api/v1/";

/// Client that holds the api key and sends requests
#[derive(Debug, Clone)]
pub struct Client {
	api_key: String,
	base_uri: String,
	user_agent: String,
}

#[allow(unused)]
impl Client {
	/// Create a new api client with a given api key
	pub fn new(api_key: String) -> Self
	{
		let crates_name = env::var("CARGO_PKG_NAME").unwrap_or("unknown".to_string());

		let crates_version = &env::var("CARGO_PKG_VERSION").unwrap_or("unknown".to_string());

		let ua = format!("libproxer-rust({}/v{})", crates_name, crates_version);

		Self {
			api_key: api_key,
			base_uri: API_BASE_PATH.to_string(),
			user_agent: ua,
		}
	}

	/// load api key from an environment variable
	pub fn with_env_key(env_key: &str) -> Option<Client>
	{
		match env::var_os(env_key)
		{
			Some(r) => Some(Client::new(r.into_string().unwrap())),
			None => None,
		}
	}

	/// execute a request that satisfies [`Endpoint`](../trait.Endpoint.html)
	pub fn execute<T: super::Endpoint + Clone + fmt::Debug>(
		&self,
		mut endpoint: T,
	) -> Result<T::ResponseType, error::Error>
	{

		let uristring = self.base_uri.to_string() + T::URL;

		header!{(ProxerApiKey, "Proxer-Api-Key") => [String]}

		let mut headers = reqwest::header::Headers::new();

		headers.set(header::UserAgent::new(self.user_agent.to_string()));
		headers.set(header::Host::new("proxer.me", None));
		headers.set(header::ContentType::form_url_encoded());
		headers.set(ProxerApiKey(self.api_key.clone()));

		let mut http_req = reqwest::Request::new(reqwest::Method::Post, uristring.parse().unwrap());

		// add our headers to the request
		http_req.headers_mut().extend(headers.iter());

		match serde_urlencoded::to_string(endpoint.clone())
		{
			Ok(body) => {
				debug!("post data: {}", body);
				*http_req.body_mut() = Some(body.into());
			}
			Err(err) => panic!("can't serialize form parameters"),
		}

		let client = reqwest::Client::new();

		let response = client.execute(http_req);

		// This section needs some rewriting. maybe... later
		match response
		{
			Err(e) => return Err(error::Error::Http),
			Ok(mut res) => {
				let mut json_string = String::new();
				res.read_to_string(&mut json_string);

				match serde_json::from_str::<ApiResponse<T::ResponseType>>(&json_string)
				{
					Err(e) => return Err(error::Error::Json(e)),
					Ok(r) => {
						if r.error != 0 {
							Err(error::Error::Api(error::api::Api::new(r.code.unwrap(), r.message)))
						}
						else {
							Ok(r.data.unwrap())
						}
					}
				}
			}
		}
	}
}

/// responses are parsed into ApiRequest
#[derive(Debug, Clone, Deserialize)]
pub struct ApiResponse<T> {
	/// api error
	pub error: i64,
	/// api message
	pub message: String,
	/// actual data
	pub data: Option<T>,
	/// optional error code
	/// in case of an error this contains the error code
	pub code: Option<i64>,
}
<|endoftext|>


<commit_before>//! The `conductor up` command.

use command_runner::{Command, CommandRunner};
#[cfg(test)]
use command_runner::TestCommandRunner;
use ovr::Override;
use project::Project;
use util::Error;

/// We implement `conductor up` with a trait so we put it in its own module.
pub trait CommandUp {
    /// Up all the images associated with a project.
    fn up<CR>(&self, runner: &CR, ovr: &Override) -> Result<(), Error>
        where CR: CommandRunner;
}

impl CommandUp for Project {
    fn up<CR>(&self, runner: &CR, ovr: &Override) -> Result<(), Error>
        where CR: CommandRunner
    {
        for pod in self.pods() {
            // We pass `-d` because we need to detach from each pod to
            // launch the next.  To avoid this, we're need to use multiple
            // parallel threads and maybe some intelligent output
            // buffering.
            let ovr_rel_path = try!(pod.override_rel_path(ovr));
            let status = try!(runner.build("docker-compose")
                .arg("-f").arg(self.output_pods_dir().join(pod.rel_path()))
                .arg("-f").arg(self.output_pods_dir().join(ovr_rel_path))
                .arg("up").arg("-d")
                .status());
            if !status.success() {
                return Err(err!("Error running docker-compose"));
            }
        }
        Ok(())
    }
}

#[test]
fn runs_docker_compose_up_on_all_pods() {
    let proj = Project::from_example("hello").unwrap();
    let ovr = proj.ovr("development").unwrap();
    let runner = TestCommandRunner::new();
    proj.output().unwrap();
    proj.up(&runner, &ovr).unwrap();
    assert_ran!(runner, {
        ["docker-compose",
         "-f", proj.output_dir().join("pods/frontend.yml"),
         "-f", proj.output_dir().join("pods/overrides/development/frontend.yml"),
         "up", "-d"]
    });
}
<commit_msg>Use `-p` to name services after the pod they're in<commit_after>//! The `conductor up` command.

use command_runner::{Command, CommandRunner};
#[cfg(test)]
use command_runner::TestCommandRunner;
use ovr::Override;
use project::Project;
use util::Error;

/// We implement `conductor up` with a trait so we put it in its own module.
pub trait CommandUp {
    /// Up all the images associated with a project.
    fn up<CR>(&self, runner: &CR, ovr: &Override) -> Result<(), Error>
        where CR: CommandRunner;
}

impl CommandUp for Project {
    fn up<CR>(&self, runner: &CR, ovr: &Override) -> Result<(), Error>
        where CR: CommandRunner
    {
        for pod in self.pods() {
            // We pass `-d` because we need to detach from each pod to
            // launch the next.  To avoid this, we'd need to use multiple
            // parallel threads and maybe some intelligent output
            // buffering.
            let ovr_rel_path = try!(pod.override_rel_path(ovr));
            let status = try!(runner.build("docker-compose")
                .arg("-p").arg(pod.name())
                .arg("-f").arg(self.output_pods_dir().join(pod.rel_path()))
                .arg("-f").arg(self.output_pods_dir().join(ovr_rel_path))
                .arg("up").arg("-d")
                .status());
            if !status.success() {
                return Err(err!("Error running docker-compose"));
            }
        }
        Ok(())
    }
}

#[test]
fn runs_docker_compose_up_on_all_pods() {
    let proj = Project::from_example("hello").unwrap();
    let ovr = proj.ovr("development").unwrap();
    let runner = TestCommandRunner::new();
    proj.output().unwrap();
    proj.up(&runner, &ovr).unwrap();
    assert_ran!(runner, {
        ["docker-compose",
         "-p", "frontend",
         "-f", proj.output_dir().join("pods/frontend.yml"),
         "-f", proj.output_dir().join("pods/overrides/development/frontend.yml"),
         "up", "-d"]
    });
}
<|endoftext|>


<commit_before>
use std::io::{Read, Write};
use std::default::Default;

use num::traits::ToPrimitive;
use byteorder::{ByteOrder, BigEndian, ReadBytesExt, WriteBytesExt};

use error::{Result, Error};

pub trait ToByte {
    fn encode<T: Write>(&self, buffer: &mut T) -> Result<()>;
    fn encode_nolen<T: Write>(&self, buffer: &mut T)  -> Result<()> {
        self.encode(buffer)
    }
}

pub trait FromByte {
    type R: Default + FromByte;

    fn decode<T: Read>(&mut self, buffer: &mut T) -> Result<()>;
    fn decode_new<T: Read>(buffer: &mut T) -> Result<Self::R> {
        let mut temp: Self::R = Default::default();
        match temp.decode(buffer) {
            Ok(_) => Ok(temp),
            Err(e) => Err(e)
        }
    }
}

impl ToByte for i8 {
    fn encode<T:Write>(&self, buffer: &mut T) -> Result<()> {
        buffer.write_i8(*self).or_else(|e| Err(From::from(e)))
    }
}

impl ToByte for i16 {
    fn encode<T:Write>(&self, buffer: &mut T) -> Result<()> {
        buffer.write_i16::<BigEndian>(*self).or_else(|e| Err(From::from(e)))
    }
}
impl ToByte for i32 {
    fn encode<T:Write>(&self, buffer: &mut T) -> Result<()> {
        buffer.write_i32::<BigEndian>(*self).or_else(|e| Err(From::from(e)))
    }
}
impl ToByte for i64 {
    fn encode<T:Write>(&self, buffer: &mut T) -> Result<()> {
        buffer.write_i64::<BigEndian>(*self).or_else(|e| Err(From::from(e)))
    }
}
impl ToByte for String {
    fn encode<T:Write>(&self, buffer: &mut T) -> Result<()> {
        let l = try!(self.len()
                        .to_i16()
                        .ok_or(Error::CodecError));
        try!(buffer.write_i16::<BigEndian>(l));
        buffer.write_all(self.as_bytes())
                             .or_else(|e| Err(From::from(e)))
    }
}

impl <V:ToByte> ToByte for Vec<V> {
    fn encode<T:Write>(&self, buffer: &mut T) -> Result<()> {
        let l = try!(self.len()
                        .to_i32()
                        .ok_or(Error::CodecError));
        try!(buffer.write_i32::<BigEndian>(l));
        for e in self {
            try!(e.encode(buffer));
        }
        Ok(())
    }
    fn encode_nolen<T:Write>(&self, buffer: &mut T) -> Result<()> {
        for e in self {
            try!(e.encode(buffer));
        }
        Ok(())
    }
}

impl ToByte for Vec<u8>{
    fn encode<T: Write>(&self, buffer: &mut T) -> Result<()> {
        let l = try!(self.len()
                        .to_i32()
                        .ok_or(Error::CodecError));
        try!(buffer.write_i32::<BigEndian>(l));
        buffer.write_all(self).or_else(|e| Err(From::from(e)))
    }
    fn encode_nolen<T: Write>(&self, buffer: &mut T) -> Result<()> {
        buffer.write_all(self).or_else(|e| Err(From::from(e)))
    }
}

macro_rules! dec_helper {
    ($val: expr, $dest:expr) => ({
        match $val {
            Ok(val) => {
                *$dest = val;
                Ok(())
                },
            Err(e) => Err(From::from(e))
        }
    })
}
macro_rules! decode {
    ($src:expr, $dest:expr) => ({
        dec_helper!($src.read_i8(), $dest)

    });
    ($src:expr, $method:ident, $dest:expr) => ({
        dec_helper!($src.$method::<BigEndian>(), $dest)

    });
}

impl FromByte for i8 {
    type R = i8;

    fn decode<T: Read>(&mut self, buffer: &mut T) -> Result<()> {
        decode!(buffer, self)
    }
}

impl FromByte for i16 {
    type R = i16;

    fn decode<T: Read>(&mut self, buffer: &mut T) -> Result<()> {
        decode!(buffer, read_i16, self)
    }
}
impl FromByte for i32 {
    type R = i32;

    fn decode<T: Read>(&mut self, buffer: &mut T) -> Result<()> {
        decode!(buffer, read_i32, self)
    }
}
impl FromByte for i64 {
    type R = i64;
    fn decode<T: Read>(&mut self, buffer: &mut T) -> Result<()> {
        decode!(buffer, read_i64, self)
    }
}
impl FromByte for String {
    type R = String;
    fn decode<T: Read>(&mut self, buffer: &mut T) -> Result<()> {
        let mut length: i16 = 0;
        match decode!(buffer, read_i16, &mut length) {
            Ok(_) => {},
            Err(e) => return Err(e)
        }
        let _ = buffer.take(length as u64).read_to_string(self);
        if self.len() != length as usize {
            return Err(Error::UnexpectedEOF);
        }
        Ok(())
    }
}

impl <V: FromByte + Default> FromByte for Vec<V>{
    type R = Vec<V>;

    fn decode<T: Read>(&mut self, buffer: &mut T) -> Result<()> {
        let mut length: i32 = 0;
        match decode!(buffer, read_i32, &mut length) {
            Ok(_) => {},
            Err(e) => return Err(e)
        }
        for _ in 0..length {
            let mut e: V = Default::default();
            try!(e.decode(buffer));
            self.push(e);
        }
        Ok(())
    }
}

impl FromByte for Vec<u8>{
    type R = Vec<u8>;

    fn decode<T: Read>(&mut self, buffer: &mut T) -> Result<()> {
        let mut length: i32 = 0;
        match decode!(buffer, read_i32, &mut length) {
            Ok(_) => {},
            Err(e) => return Err(e)
        }
        if length <= 0 {return Ok(());}
        match buffer.take(length as u64).read_to_end(self) {
            Ok(size) => {
                if size < length as usize {
                    return Err(Error::UnexpectedEOF)
                } else {
                    Ok(())
                }
            },
            Err(e) => Err(From::from(e))
        }
    }
}

#[test]
fn codec_i8() {
    use std::io::Cursor;
    let mut buf = vec!();
    let orig: i8 = 5;

    // Encode into buffer
    orig.encode(&mut buf).unwrap();
    assert_eq!(buf, [5]);

    // Read from buffer into existing variable
    let mut dec1: i8 = 0;
    dec1.decode(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec1, orig);

    // Read from buffer into new variable
    let dec2 = i8::decode_new(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec2, orig);
}

#[test]
fn codec_i16() {
    use std::io::Cursor;
    let mut buf = vec!();
    let orig: i16 = 5;

    // Encode into buffer
    orig.encode(&mut buf).unwrap();
    assert_eq!(buf, [0, 5]);

    // Read from buffer into existing variable
    let mut dec1: i16 = 0;
    dec1.decode(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec1, orig);

    // Read from buffer into new variable
    let dec2 = i16::decode_new(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec2, orig);
}

#[test]
fn codec_32() {
    use std::io::Cursor;
    let mut buf = vec!();
    let orig: i32 = 5;

    // Encode into buffer
    orig.encode(&mut buf).unwrap();
    assert_eq!(buf, [0, 0, 0, 5]);

    // Read from buffer into existing variable
    let mut dec1: i32 = 0;
    dec1.decode(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec1, orig);

    // Read from buffer into new variable
    let dec2 = i32::decode_new(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec2, orig);
}

#[test]
fn codec_i64() {
    use std::io::Cursor;
    let mut buf = vec!();
    let orig: i64 = 5;

    // Encode into buffer
    orig.encode(&mut buf).unwrap();
    assert_eq!(buf, [0, 0, 0, 0, 0, 0, 0, 5]);

    // Read from buffer into existing variable
    let mut dec1: i64 = 0;
    dec1.decode(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec1, orig);

    // Read from buffer into new variable
    let dec2 = i64::decode_new(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec2, orig);
}

#[test]
fn codec_string() {
    use std::io::Cursor;
    let mut buf = vec!();
    let orig = "test".to_owned();

    // Encode into buffer
    orig.encode(&mut buf).unwrap();
    assert_eq!(buf, [0, 4, 116, 101, 115, 116]);

    // Read from buffer into existing variable
    let mut dec1 = String::new();
    dec1.decode(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec1, orig);

    // Read from buffer into new variable
    let dec2 = String::decode_new(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec2, orig);
}

#[test]
fn codec_vec_u8() {
    use std::io::Cursor;
    let mut buf = vec!();
    let orig: Vec<u8> = vec!(1, 2, 3);

    // Encode into buffer
    orig.encode(&mut buf).unwrap();
    assert_eq!(buf, [0, 0, 0, 3, 1, 2, 3]);

    // Read from buffer into existing variable
    let mut dec1: Vec<u8> = vec!();
    dec1.decode(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec1, orig);

    // Read from buffer into new variable
    let dec2 = Vec::<u8>::decode_new(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec2, orig);
}
<commit_msg>#! Avoid reallocations while decoding String and Vectors<commit_after>
use std::io::{Read, Write};
use std::default::Default;

use num::traits::ToPrimitive;
use byteorder::{ByteOrder, BigEndian, ReadBytesExt, WriteBytesExt};

use error::{Result, Error};

pub trait ToByte {
    fn encode<T: Write>(&self, buffer: &mut T) -> Result<()>;
    fn encode_nolen<T: Write>(&self, buffer: &mut T)  -> Result<()> {
        self.encode(buffer)
    }
}

pub trait FromByte {
    type R: Default + FromByte;

    fn decode<T: Read>(&mut self, buffer: &mut T) -> Result<()>;
    fn decode_new<T: Read>(buffer: &mut T) -> Result<Self::R> {
        let mut temp: Self::R = Default::default();
        match temp.decode(buffer) {
            Ok(_) => Ok(temp),
            Err(e) => Err(e)
        }
    }
}

impl ToByte for i8 {
    fn encode<T:Write>(&self, buffer: &mut T) -> Result<()> {
        buffer.write_i8(*self).or_else(|e| Err(From::from(e)))
    }
}

impl ToByte for i16 {
    fn encode<T:Write>(&self, buffer: &mut T) -> Result<()> {
        buffer.write_i16::<BigEndian>(*self).or_else(|e| Err(From::from(e)))
    }
}
impl ToByte for i32 {
    fn encode<T:Write>(&self, buffer: &mut T) -> Result<()> {
        buffer.write_i32::<BigEndian>(*self).or_else(|e| Err(From::from(e)))
    }
}
impl ToByte for i64 {
    fn encode<T:Write>(&self, buffer: &mut T) -> Result<()> {
        buffer.write_i64::<BigEndian>(*self).or_else(|e| Err(From::from(e)))
    }
}
impl ToByte for String {
    fn encode<T:Write>(&self, buffer: &mut T) -> Result<()> {
        let l = try!(self.len()
                        .to_i16()
                        .ok_or(Error::CodecError));
        try!(buffer.write_i16::<BigEndian>(l));
        buffer.write_all(self.as_bytes())
                             .or_else(|e| Err(From::from(e)))
    }
}

impl <V:ToByte> ToByte for Vec<V> {
    fn encode<T:Write>(&self, buffer: &mut T) -> Result<()> {
        let l = try!(self.len()
                        .to_i32()
                        .ok_or(Error::CodecError));
        try!(buffer.write_i32::<BigEndian>(l));
        for e in self {
            try!(e.encode(buffer));
        }
        Ok(())
    }
    fn encode_nolen<T:Write>(&self, buffer: &mut T) -> Result<()> {
        for e in self {
            try!(e.encode(buffer));
        }
        Ok(())
    }
}

impl ToByte for Vec<u8>{
    fn encode<T: Write>(&self, buffer: &mut T) -> Result<()> {
        let l = try!(self.len()
                        .to_i32()
                        .ok_or(Error::CodecError));
        try!(buffer.write_i32::<BigEndian>(l));
        buffer.write_all(self).or_else(|e| Err(From::from(e)))
    }
    fn encode_nolen<T: Write>(&self, buffer: &mut T) -> Result<()> {
        buffer.write_all(self).or_else(|e| Err(From::from(e)))
    }
}

macro_rules! dec_helper {
    ($val: expr, $dest:expr) => ({
        match $val {
            Ok(val) => {
                *$dest = val;
                Ok(())
                },
            Err(e) => Err(From::from(e))
        }
    })
}
macro_rules! decode {
    ($src:expr, $dest:expr) => ({
        dec_helper!($src.read_i8(), $dest)

    });
    ($src:expr, $method:ident, $dest:expr) => ({
        dec_helper!($src.$method::<BigEndian>(), $dest)

    });
}

impl FromByte for i8 {
    type R = i8;

    fn decode<T: Read>(&mut self, buffer: &mut T) -> Result<()> {
        decode!(buffer, self)
    }
}

impl FromByte for i16 {
    type R = i16;

    fn decode<T: Read>(&mut self, buffer: &mut T) -> Result<()> {
        decode!(buffer, read_i16, self)
    }
}
impl FromByte for i32 {
    type R = i32;

    fn decode<T: Read>(&mut self, buffer: &mut T) -> Result<()> {
        decode!(buffer, read_i32, self)
    }
}
impl FromByte for i64 {
    type R = i64;
    fn decode<T: Read>(&mut self, buffer: &mut T) -> Result<()> {
        decode!(buffer, read_i64, self)
    }
}
impl FromByte for String {
    type R = String;
    fn decode<T: Read>(&mut self, buffer: &mut T) -> Result<()> {
        let mut length: i16 = 0;
        if let Err(e) = decode!(buffer, read_i16, &mut length) {
            return Err(e);
        }
        if length <= 0 { return Ok(()); }
        self.reserve(length as usize);
        let _ = buffer.take(length as u64).read_to_string(self);
        if self.len() != length as usize {
            return Err(Error::UnexpectedEOF);
        }
        Ok(())
    }
}

impl <V: FromByte + Default> FromByte for Vec<V>{
    type R = Vec<V>;

    fn decode<T: Read>(&mut self, buffer: &mut T) -> Result<()> {
        let mut length: i32 = 0;
        if let Err(e) = decode!(buffer, read_i32, &mut length) {
            return Err(e);
        }
        if length <= 0 { return Ok(()); }
        self.reserve(length as usize);
        for _ in 0..length {
            let mut e: V = Default::default();
            try!(e.decode(buffer));
            self.push(e);
        }
        Ok(())
    }
}

impl FromByte for Vec<u8>{
    type R = Vec<u8>;

    fn decode<T: Read>(&mut self, buffer: &mut T) -> Result<()> {
        let mut length: i32 = 0;
        match decode!(buffer, read_i32, &mut length) {
            Ok(_) => {},
            Err(e) => return Err(e)
        }
        if length <= 0 {return Ok(());}
        self.reserve(length as usize);
        match buffer.take(length as u64).read_to_end(self) {
            Ok(size) => {
                if size < length as usize {
                    return Err(Error::UnexpectedEOF)
                } else {
                    Ok(())
                }
            },
            Err(e) => Err(From::from(e))
        }
    }
}

#[test]
fn codec_i8() {
    use std::io::Cursor;
    let mut buf = vec!();
    let orig: i8 = 5;

    // Encode into buffer
    orig.encode(&mut buf).unwrap();
    assert_eq!(buf, [5]);

    // Read from buffer into existing variable
    let mut dec1: i8 = 0;
    dec1.decode(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec1, orig);

    // Read from buffer into new variable
    let dec2 = i8::decode_new(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec2, orig);
}

#[test]
fn codec_i16() {
    use std::io::Cursor;
    let mut buf = vec!();
    let orig: i16 = 5;

    // Encode into buffer
    orig.encode(&mut buf).unwrap();
    assert_eq!(buf, [0, 5]);

    // Read from buffer into existing variable
    let mut dec1: i16 = 0;
    dec1.decode(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec1, orig);

    // Read from buffer into new variable
    let dec2 = i16::decode_new(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec2, orig);
}

#[test]
fn codec_32() {
    use std::io::Cursor;
    let mut buf = vec!();
    let orig: i32 = 5;

    // Encode into buffer
    orig.encode(&mut buf).unwrap();
    assert_eq!(buf, [0, 0, 0, 5]);

    // Read from buffer into existing variable
    let mut dec1: i32 = 0;
    dec1.decode(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec1, orig);

    // Read from buffer into new variable
    let dec2 = i32::decode_new(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec2, orig);
}

#[test]
fn codec_i64() {
    use std::io::Cursor;
    let mut buf = vec!();
    let orig: i64 = 5;

    // Encode into buffer
    orig.encode(&mut buf).unwrap();
    assert_eq!(buf, [0, 0, 0, 0, 0, 0, 0, 5]);

    // Read from buffer into existing variable
    let mut dec1: i64 = 0;
    dec1.decode(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec1, orig);

    // Read from buffer into new variable
    let dec2 = i64::decode_new(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec2, orig);
}

#[test]
fn codec_string() {
    use std::io::Cursor;
    let mut buf = vec!();
    let orig = "test".to_owned();

    // Encode into buffer
    orig.encode(&mut buf).unwrap();
    assert_eq!(buf, [0, 4, 116, 101, 115, 116]);

    // Read from buffer into existing variable
    let mut dec1 = String::new();
    dec1.decode(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec1, orig);

    // Read from buffer into new variable
    let dec2 = String::decode_new(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec2, orig);
}

#[test]
fn codec_vec_u8() {
    use std::io::Cursor;
    let mut buf = vec!();
    let orig: Vec<u8> = vec!(1, 2, 3);

    // Encode into buffer
    orig.encode(&mut buf).unwrap();
    assert_eq!(buf, [0, 0, 0, 3, 1, 2, 3]);

    // Read from buffer into existing variable
    let mut dec1: Vec<u8> = vec!();
    dec1.decode(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec1, orig);

    // Read from buffer into new variable
    let dec2 = Vec::<u8>::decode_new(&mut Cursor::new(buf.clone())).unwrap();
    assert_eq!(dec2, orig);
}
<|endoftext|>


<commit_before>
use std::env;
use hyper::Uri;

use crate::{Context, ContextBuilder};

const DEFAULT_HOSTNAME: &'static str = "https://airbrake.io";
const ENV_VAR_PROJECT_ID: &'static str = "AIRBRAKE_PROJECT_ID";
const ENV_VAR_PROJECT_KEY: &'static str = "AIRBRAKE_API_KEY";
const ENV_VAR_HOST: &'static str = "AIRBRAKE_HOST";

#[derive(Debug, PartialEq)]
pub enum AirbrakeConfigError {
    MissingProjectId,
    MissingProjectKey,
    EmptyProjectId,
    EmptyProjectKey
}

pub struct AirbrakeConfigBuilder {
    pub project_id: Option<String>,
    pub project_key: Option<String>,
    pub host: Option<String>,
    pub proxy: Option<String>,
    pub context: Option<ContextBuilder>,
}

impl AirbrakeConfigBuilder {
    pub fn new() -> AirbrakeConfigBuilder {
        AirbrakeConfigBuilder {
            project_id: None,
            project_key: None,
            host: None,
            proxy: None,
            context: None,
        }
    }

    pub fn configure<F>(&mut self, builder_callback: F) -> &mut AirbrakeConfigBuilder
    where F: Fn(&mut AirbrakeConfigBuilder)
    {
        builder_callback(self);
        self
    }

    pub fn project<'a>(&'a mut self, project_id: String, project_key: String) -> &'a mut AirbrakeConfigBuilder {
        self.project_id(project_id)
            .project_key(project_key)
    }

    pub fn project_id<'a>(&'a mut self, project_id: String) -> &'a mut AirbrakeConfigBuilder {
        self.project_id = Some(project_id);
        self
    }

    /// Builder can pull env vars from environment
    ///
    /// ```
    /// use std::env;
    /// use airbrake::AirbrakeConfig;
    ///
    /// // Set vars to set up our test
    /// env::set_var("AIRBRAKE_PROJECT_ID", "foo");
    /// env::set_var("AIRBRAKE_API_KEY", "bar");
    ///
    /// // Now build the config using just the environment variables
    /// let config = AirbrakeConfig::builder()
    ///     .project_id_from_env().expect("missing id")
    ///     .project_key_from_env().expect("missing key")
    ///     .build();
    /// ```
    ///
    /// If you wanted to handle more complex logic around the
    /// environment variables
    ///
    /// ```
    /// use std::env;
    /// use airbrake::AirbrakeConfig;
    ///
    /// // Set defaults to use if env vars are missing
    /// let default_project_id = "foo".to_owned();
    /// let default_project_key = "bar".to_owned();
    ///
    /// // Only set the project key using the env var
    /// env::set_var("AIRBRAKE_API_KEY", "baz");
    ///
    /// // Begin constructing a config builder
    /// let mut config = AirbrakeConfig::builder();
    /// if config.project_id_from_env().is_err() {
    ///     config.project_id(default_project_id);
    /// }
    /// if config.project_key_from_env().is_err() {
    ///     config.project_key(default_project_key);
    /// }
    /// let config = config.build().unwrap();
    /// assert_eq!(config.project_id, "foo");
    /// assert_eq!(config.project_key, "baz");
    /// ```
    ///
    pub fn project_id_from_env<'a>(&'a mut self) -> Result<&'a mut AirbrakeConfigBuilder, env::VarError> {
        match env::var(ENV_VAR_PROJECT_ID) {
            Ok(val) => {
                self.project_id = Some(val);
                Ok(self)
            },
            Err(e) => Err(e),
        }
    }

    pub fn project_key_from_env<'a>(&'a mut self) -> Result<&'a mut AirbrakeConfigBuilder, env::VarError> {
        match env::var(ENV_VAR_PROJECT_KEY) {
            Ok(val) => {
                self.project_key = Some(val);
                Ok(self)
            },
            Err(e) => Err(e),
        }
    }

    pub fn project_key<'a>(&'a mut self, project_key: String) -> &'a mut AirbrakeConfigBuilder {
        self.project_key = Some(project_key);
        self
    }

    pub fn host_from_env<'a>(&'a mut self) -> Result<&'a mut AirbrakeConfigBuilder, env::VarError> {
        match env::var(ENV_VAR_HOST) {
            Ok(val) => {
                self.host = Some(val);
                Ok(self)
            },
            Err(e) => Err(e),
        }
    }

    pub fn host<'a>(&'a mut self, host: String) -> &'a mut AirbrakeConfigBuilder {
        self.host = Some(host);
        self
    }

    pub fn proxy<'a>(&'a mut self, proxy: String) -> &'a mut AirbrakeConfigBuilder {
        self.proxy = Some(proxy);
        self
    }

    // Context configuration functions

    pub fn context<'a>(&'a mut self, context: ContextBuilder) -> &'a mut AirbrakeConfigBuilder {
        self.context = Some(context);
        self
    }

    pub fn operating_system<'a>(&'a mut self, os: String) -> &'a mut AirbrakeConfigBuilder {
        self.context = self.context
            .clone()
            .or_else(|| Some(Context::builder()))
            .and_then(|mut c| {
                c.operating_system(os);
                Some(c)
            });
        self
    }

    pub fn build(&self) -> Result<AirbrakeConfig, AirbrakeConfigError> {
        let project_id = match &self.project_id {
            Some( id ) => id,
            None => return Err( AirbrakeConfigError::MissingProjectId )
        };
        let project_key = match &self.project_key {
            Some( key ) => key,
            None => return Err( AirbrakeConfigError::MissingProjectKey )
        };
        if project_id.is_empty() {
            return Err( AirbrakeConfigError::EmptyProjectId )
        }
        if project_key.is_empty() {
            return Err( AirbrakeConfigError::EmptyProjectKey )
        }
        let context = self.context.clone().and_then(|c| Some(c.build()));

        Ok(AirbrakeConfig {
            project_id: project_id.to_string(),
            project_key: project_key.to_string(),
            host: self.host.clone().unwrap_or(DEFAULT_HOSTNAME.to_owned()),
            proxy: self.proxy.clone(),
            context: context
        })
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct AirbrakeConfig {
    pub project_id: String,
    pub project_key: String,
    pub host: String,
    pub proxy: Option<String>,
    pub context: Option<Context>
}

impl AirbrakeConfig {
    /// Enables easy creation of the config object
    ///
    /// ```
    /// use airbrake::AirbrakeConfig;
    ///
    /// let my_project_id = "foo".to_owned();
    /// let my_project_key = "bar".to_owned();
    /// let config = AirbrakeConfig::builder()
    ///     .project(my_project_id, my_project_key)
    ///     .build();
    /// ```
    pub fn builder() -> AirbrakeConfigBuilder {
        AirbrakeConfigBuilder::new()
    }

    pub fn new(project_id: String, project_key: String) -> Result<AirbrakeConfig, AirbrakeConfigError> {
        AirbrakeConfig::builder()
            .project_id(project_id)
            .project_key(project_key)
            .build()
    }

    pub fn endpoint(&self) -> String {
        format!(
            "{}/api/v3/projects/{}/notices?key={}",
            self.host,
            self.project_id,
            self.project_key,
        )
    }

    pub fn endpoint_uri(&self) -> Uri {
        self.endpoint().parse().expect("malformed URL")
    }
}

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

    #[test]
    fn endpoint_defaults_to_airbrake_server() {
        let project_id = "foo".to_owned();
        let project_key = "bar".to_owned();
        let config = AirbrakeConfig::builder()
            .project_id(project_id)
            .project_key(project_key)
            .build();
        assert_eq!(
            "https://airbrake.io/api/v3/projects/foo/notices?key=bar",
            config.unwrap().endpoint_uri()
        );
    }

    #[test]
    fn project_sets_both_id_and_key() {
        let project_id = "foo".to_owned();
        let project_key = "bar".to_owned();
        let config1 = AirbrakeConfig::builder()
            .project(project_id.clone(), project_key.clone())
            .build();
        let config2 = AirbrakeConfig::builder()
            .project_id(project_id)
            .project_key(project_key)
            .build();
        assert_eq!(config1, config2);
        assert_eq!(
            "https://airbrake.io/api/v3/projects/foo/notices?key=bar",
            config1.unwrap().endpoint_uri()
        )
    }

    #[test]
    fn config_build_fails_on_empty_project_id() {
        let config = AirbrakeConfig::builder()
            .project_id("".to_owned())
            .project_key("bar".to_owned())
            .build();
        assert_eq!(config, Err(AirbrakeConfigError::EmptyProjectId))
    }

    #[test]
    fn config_build_fails_on_empty_project_key() {
        let config = AirbrakeConfig::builder()
            .project_id("foo".to_owned())
            .project_key("".to_owned())
            .build();
        assert_eq!(config, Err(AirbrakeConfigError::EmptyProjectKey))
    }

    #[test]
    fn default_builder_fails_build() {
        let config = AirbrakeConfig::builder().build();
        assert_eq!(config, Err(AirbrakeConfigError::MissingProjectId))
    }

    #[test]
    fn config_build_fails_on_missing_project_id() {
        let config = AirbrakeConfig::builder()
            .project_key("bar".to_owned())
            .build();
        assert_eq!(config, Err(AirbrakeConfigError::MissingProjectId))
    }

    #[test]
    fn config_build_fails_on_missing_project_key() {
        let config = AirbrakeConfig::builder()
            .project_id("foo".to_owned())
            .build();
        assert_eq!(config, Err(AirbrakeConfigError::MissingProjectKey))
    }
}
<commit_msg>Config builder can set all context fields<commit_after>
use std::env;
use hyper::Uri;

use crate::{Context, ContextBuilder, ContextUser};

const DEFAULT_HOSTNAME: &'static str = "https://airbrake.io";
const ENV_VAR_PROJECT_ID: &'static str = "AIRBRAKE_PROJECT_ID";
const ENV_VAR_PROJECT_KEY: &'static str = "AIRBRAKE_API_KEY";
const ENV_VAR_HOST: &'static str = "AIRBRAKE_HOST";

#[derive(Debug, PartialEq)]
pub enum AirbrakeConfigError {
    MissingProjectId,
    MissingProjectKey,
    EmptyProjectId,
    EmptyProjectKey
}

pub struct AirbrakeConfigBuilder {
    pub project_id: Option<String>,
    pub project_key: Option<String>,
    pub host: Option<String>,
    pub proxy: Option<String>,
    pub context: Option<ContextBuilder>,
}

impl AirbrakeConfigBuilder {
    pub fn new() -> AirbrakeConfigBuilder {
        AirbrakeConfigBuilder {
            project_id: None,
            project_key: None,
            host: None,
            proxy: None,
            context: None,
        }
    }

    pub fn configure<F>(&mut self, builder_callback: F) -> &mut AirbrakeConfigBuilder
    where F: Fn(&mut AirbrakeConfigBuilder)
    {
        builder_callback(self);
        self
    }

    pub fn project<'a>(&'a mut self, project_id: String, project_key: String) -> &'a mut AirbrakeConfigBuilder {
        self.project_id(project_id)
            .project_key(project_key)
    }

    pub fn project_id<'a>(&'a mut self, project_id: String) -> &'a mut AirbrakeConfigBuilder {
        self.project_id = Some(project_id);
        self
    }

    /// Builder can pull env vars from environment
    ///
    /// ```
    /// use std::env;
    /// use airbrake::AirbrakeConfig;
    ///
    /// // Set vars to set up our test
    /// env::set_var("AIRBRAKE_PROJECT_ID", "foo");
    /// env::set_var("AIRBRAKE_API_KEY", "bar");
    ///
    /// // Now build the config using just the environment variables
    /// let config = AirbrakeConfig::builder()
    ///     .project_id_from_env().expect("missing id")
    ///     .project_key_from_env().expect("missing key")
    ///     .build();
    /// ```
    ///
    /// If you wanted to handle more complex logic around the
    /// environment variables
    ///
    /// ```
    /// use std::env;
    /// use airbrake::AirbrakeConfig;
    ///
    /// // Set defaults to use if env vars are missing
    /// let default_project_id = "foo".to_owned();
    /// let default_project_key = "bar".to_owned();
    ///
    /// // Only set the project key using the env var
    /// env::set_var("AIRBRAKE_API_KEY", "baz");
    ///
    /// // Begin constructing a config builder
    /// let mut config = AirbrakeConfig::builder();
    /// if config.project_id_from_env().is_err() {
    ///     config.project_id(default_project_id);
    /// }
    /// if config.project_key_from_env().is_err() {
    ///     config.project_key(default_project_key);
    /// }
    /// let config = config.build().unwrap();
    /// assert_eq!(config.project_id, "foo");
    /// assert_eq!(config.project_key, "baz");
    /// ```
    ///
    pub fn project_id_from_env<'a>(&'a mut self) -> Result<&'a mut AirbrakeConfigBuilder, env::VarError> {
        match env::var(ENV_VAR_PROJECT_ID) {
            Ok(val) => {
                self.project_id = Some(val);
                Ok(self)
            },
            Err(e) => Err(e),
        }
    }

    pub fn project_key_from_env<'a>(&'a mut self) -> Result<&'a mut AirbrakeConfigBuilder, env::VarError> {
        match env::var(ENV_VAR_PROJECT_KEY) {
            Ok(val) => {
                self.project_key = Some(val);
                Ok(self)
            },
            Err(e) => Err(e),
        }
    }

    pub fn project_key<'a>(&'a mut self, project_key: String) -> &'a mut AirbrakeConfigBuilder {
        self.project_key = Some(project_key);
        self
    }

    pub fn host_from_env<'a>(&'a mut self) -> Result<&'a mut AirbrakeConfigBuilder, env::VarError> {
        match env::var(ENV_VAR_HOST) {
            Ok(val) => {
                self.host = Some(val);
                Ok(self)
            },
            Err(e) => Err(e),
        }
    }

    pub fn host<'a>(&'a mut self, host: String) -> &'a mut AirbrakeConfigBuilder {
        self.host = Some(host);
        self
    }

    pub fn proxy<'a>(&'a mut self, proxy: String) -> &'a mut AirbrakeConfigBuilder {
        self.proxy = Some(proxy);
        self
    }

    // Sets the configurations context to an existing context builder
    pub fn context<'a>(&'a mut self, context: ContextBuilder) -> &'a mut AirbrakeConfigBuilder {
        self.context = Some(context);
        self
    }

    /// Set the operating_system on the configurations context
    pub fn operating_system<'a>(&'a mut self, os: String) -> &'a mut AirbrakeConfigBuilder {
        self.context = self.context
            .clone()
            .or_else(|| Some(Context::builder()))
            .and_then(|mut c| {
                c.operating_system(os);
                Some(c)
            });
        self
    }

    /// Set the hostname on the configurations context
    pub fn hostname<'a>(&'a mut self, hostname: String) -> &'a mut AirbrakeConfigBuilder {
        self.context = self.context
            .clone()
            .or_else(|| Some(Context::builder()))
            .and_then(|mut c| {
                c.hostname(hostname);
                Some(c)
            });
        self
    }

    /// Set the language on the configurations context
    pub fn language<'a>(&'a mut self, language: String) -> &'a mut AirbrakeConfigBuilder {
        self.context = self.context
            .clone()
            .or_else(|| Some(Context::builder()))
            .and_then(|mut c| {
                c.language(language);
                Some(c)
            });
        self
    }

    /// Set the environment on the configurations context
    pub fn environment<'a>(&'a mut self, environment: String) -> &'a mut AirbrakeConfigBuilder {
        self.context = self.context
            .clone()
            .or_else(|| Some(Context::builder()))
            .and_then(|mut c| {
                c.environment(environment);
                Some(c)
            });
        self
    }

    /// Set the severity on the configurations context
    pub fn severity<'a>(&'a mut self, severity: String) -> &'a mut AirbrakeConfigBuilder {
        self.context = self.context
            .clone()
            .or_else(|| Some(Context::builder()))
            .and_then(|mut c| {
                c.severity(severity);
                Some(c)
            });
        self
    }

    /// Set the version on the configurations context
    pub fn version<'a>(&'a mut self, version: String) -> &'a mut AirbrakeConfigBuilder {
        self.context = self.context
            .clone()
            .or_else(|| Some(Context::builder()))
            .and_then(|mut c| {
                c.version(version);
                Some(c)
            });
        self
    }

    /// Set the url on the configurations context
    pub fn url<'a>(&'a mut self, url: String) -> &'a mut AirbrakeConfigBuilder {
        self.context = self.context
            .clone()
            .or_else(|| Some(Context::builder()))
            .and_then(|mut c| {
                c.url(url);
                Some(c)
            });
        self
    }

    /// Set the root_directory on the configurations context
    pub fn root_directory<'a>(&'a mut self, root_directory: String) -> &'a mut AirbrakeConfigBuilder {
        self.context = self.context
            .clone()
            .or_else(|| Some(Context::builder()))
            .and_then(|mut c| {
                c.root_directory(root_directory);
                Some(c)
            });
        self
    }

    /// Set the user on the configurations context
    pub fn user<'a>(&'a mut self, user: ContextUser) -> &'a mut AirbrakeConfigBuilder {
        self.context = self.context
            .clone()
            .or_else(|| Some(Context::builder()))
            .and_then(|mut c| {
                c.user(user);
                Some(c)
            });
        self
    }

    /// Set the route on the configurations context
    pub fn route<'a>(&'a mut self, route: String) -> &'a mut AirbrakeConfigBuilder {
        self.context = self.context
            .clone()
            .or_else(|| Some(Context::builder()))
            .and_then(|mut c| {
                c.route(route);
                Some(c)
            });
        self
    }

    /// Set the http_method on the configurations context
    pub fn http_method<'a>(&'a mut self, http_method: String) -> &'a mut AirbrakeConfigBuilder {
        self.context = self.context
            .clone()
            .or_else(|| Some(Context::builder()))
            .and_then(|mut c| {
                c.http_method(http_method);
                Some(c)
            });
        self
    }

    pub fn build(&self) -> Result<AirbrakeConfig, AirbrakeConfigError> {
        let project_id = match &self.project_id {
            Some( id ) => id,
            None => return Err( AirbrakeConfigError::MissingProjectId )
        };
        let project_key = match &self.project_key {
            Some( key ) => key,
            None => return Err( AirbrakeConfigError::MissingProjectKey )
        };
        if project_id.is_empty() {
            return Err( AirbrakeConfigError::EmptyProjectId )
        }
        if project_key.is_empty() {
            return Err( AirbrakeConfigError::EmptyProjectKey )
        }
        let context = self.context.clone().and_then(|c| Some(c.build()));

        Ok(AirbrakeConfig {
            project_id: project_id.to_string(),
            project_key: project_key.to_string(),
            host: self.host.clone().unwrap_or(DEFAULT_HOSTNAME.to_owned()),
            proxy: self.proxy.clone(),
            context: context
        })
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct AirbrakeConfig {
    pub project_id: String,
    pub project_key: String,
    pub host: String,
    pub proxy: Option<String>,
    pub context: Option<Context>
}

impl AirbrakeConfig {
    /// Enables easy creation of the config object
    ///
    /// ```
    /// use airbrake::AirbrakeConfig;
    ///
    /// let my_project_id = "foo".to_owned();
    /// let my_project_key = "bar".to_owned();
    /// let config = AirbrakeConfig::builder()
    ///     .project(my_project_id, my_project_key)
    ///     .build();
    /// ```
    pub fn builder() -> AirbrakeConfigBuilder {
        AirbrakeConfigBuilder::new()
    }

    pub fn new(project_id: String, project_key: String) -> Result<AirbrakeConfig, AirbrakeConfigError> {
        AirbrakeConfig::builder()
            .project_id(project_id)
            .project_key(project_key)
            .build()
    }

    pub fn endpoint(&self) -> String {
        format!(
            "{}/api/v3/projects/{}/notices?key={}",
            self.host,
            self.project_id,
            self.project_key,
        )
    }

    pub fn endpoint_uri(&self) -> Uri {
        self.endpoint().parse().expect("malformed URL")
    }
}

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

    #[test]
    fn endpoint_defaults_to_airbrake_server() {
        let project_id = "foo".to_owned();
        let project_key = "bar".to_owned();
        let config = AirbrakeConfig::builder()
            .project_id(project_id)
            .project_key(project_key)
            .build();
        assert_eq!(
            "https://airbrake.io/api/v3/projects/foo/notices?key=bar",
            config.unwrap().endpoint_uri()
        );
    }

    #[test]
    fn project_sets_both_id_and_key() {
        let project_id = "foo".to_owned();
        let project_key = "bar".to_owned();
        let config1 = AirbrakeConfig::builder()
            .project(project_id.clone(), project_key.clone())
            .build();
        let config2 = AirbrakeConfig::builder()
            .project_id(project_id)
            .project_key(project_key)
            .build();
        assert_eq!(config1, config2);
        assert_eq!(
            "https://airbrake.io/api/v3/projects/foo/notices?key=bar",
            config1.unwrap().endpoint_uri()
        )
    }

    #[test]
    fn config_build_fails_on_empty_project_id() {
        let config = AirbrakeConfig::builder()
            .project_id("".to_owned())
            .project_key("bar".to_owned())
            .build();
        assert_eq!(config, Err(AirbrakeConfigError::EmptyProjectId))
    }

    #[test]
    fn config_build_fails_on_empty_project_key() {
        let config = AirbrakeConfig::builder()
            .project_id("foo".to_owned())
            .project_key("".to_owned())
            .build();
        assert_eq!(config, Err(AirbrakeConfigError::EmptyProjectKey))
    }

    #[test]
    fn default_builder_fails_build() {
        let config = AirbrakeConfig::builder().build();
        assert_eq!(config, Err(AirbrakeConfigError::MissingProjectId))
    }

    #[test]
    fn config_build_fails_on_missing_project_id() {
        let config = AirbrakeConfig::builder()
            .project_key("bar".to_owned())
            .build();
        assert_eq!(config, Err(AirbrakeConfigError::MissingProjectId))
    }

    #[test]
    fn config_build_fails_on_missing_project_key() {
        let config = AirbrakeConfig::builder()
            .project_id("foo".to_owned())
            .build();
        assert_eq!(config, Err(AirbrakeConfigError::MissingProjectKey))
    }
}
<|endoftext|>


<commit_before>use std::io::{File, Open, Read, Write};
use serialize::{json, Decodable};

use oauth::Token;

#[deriving(Show, Encodable, Decodable)]
pub struct Config {
    pub consumer_key: String,
    pub consumer_secret: String,
    pub access_key: String,
    pub access_secret: String
}

const PATH: &'static str = "./.cttw.conf";

pub fn read() -> Option<Config> {
    let path = Path::new(PATH);
    let mut file = match File::open_mode(&path, Open, Read) {
        Ok(f) => f,
        Err(_) => return None
    };
    let conf = json::from_reader(&mut file).unwrap();
    Decodable::decode(&mut json::Decoder::new(conf)).ok()
}

pub fn write(conf: &Config) {
    let path = Path::new(PATH);
    let mut file = match File::open_mode(&path, Open, Write) {
        Ok(f) => f,
        Err(e) => panic!("{}", e)
    };
    file.write_line(json::encode(conf).as_slice());
}
<commit_msg>fix warnings<commit_after>use std::io::{File, Open, Read, Write};
use serialize::{json, Decodable};

#[deriving(Show, Encodable, Decodable)]
pub struct Config {
    pub consumer_key: String,
    pub consumer_secret: String,
    pub access_key: String,
    pub access_secret: String
}

const PATH: &'static str = "./.cttw.conf";

pub fn read() -> Option<Config> {
    let path = Path::new(PATH);
    let mut file = match File::open_mode(&path, Open, Read) {
        Ok(f) => f,
        Err(_) => return None
    };
    let conf = json::from_reader(&mut file).unwrap();
    Decodable::decode(&mut json::Decoder::new(conf)).ok()
}

pub fn write(conf: &Config) {
    let path = Path::new(PATH);
    let mut file = match File::open_mode(&path, Open, Write) {
        Ok(f) => f,
        Err(e) => panic!("{}", e)
    };
    let _ = file.write_line(json::encode(conf).as_slice());
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate crypto;
extern crate rustc_serialize;

use std::borrow::BorrowMut;
use std::iter::Extend;
use self::crypto::{sha1, sha2, md5, digest};
use self::rand::Rng;
use self::rustc_serialize::base64::{ToBase64, STANDARD};

pub trait Encryptor {

    fn sha1(&self) -> String;
    fn sha256(&self) -> String;
    fn sha512(&self) -> String;
    fn md5(&self) -> String;

    fn ssha512(&self, l: usize) -> String;
    fn ssha256(&self, l: usize) -> String;

    fn encrypt<T: digest::Digest>(&self, dig: &mut T) -> String;
    fn encrypt_with_slat<T: digest::Digest>(&self, dig: &mut T, l: usize) -> String;
}

impl Encryptor for String {

    fn sha1(&self) -> String {
        let mut dig = sha1::Sha1::new();
        self.encrypt(&mut dig)
    }
    fn sha256(&self) -> String {
        let mut dig = sha2::Sha256::new();
        self.encrypt(&mut dig)
    }
    fn sha512(&self) -> String {
        let mut dig = sha2::Sha512::new();
        self.encrypt(&mut dig)
    }
    fn md5(&self) -> String {
        let mut dig = md5::Md5::new();
        self.encrypt(&mut dig)
    }

    fn ssha256(&self, l: usize) -> String {
        let mut dig = sha2::Sha256::new();
        self.encrypt_with_slat(&mut dig, l)
    }
    fn ssha512(&self, l: usize) -> String {
        let mut dig = sha2::Sha512::new();
        self.encrypt_with_slat(&mut dig, l)
    }

    fn encrypt<T: digest::Digest>(&self, dig: &mut T) -> String {
        dig.input_str(&self);
        dig.result_str()
    }
    fn encrypt_with_slat<T: digest::Digest>(&self, dig: &mut T, l: usize) -> String {
        let salt: String = rand::thread_rng().gen_ascii_chars().take(l).collect();
        let mut buf = "".to_string();
        buf.push_str(&self);
        buf.push_str(&salt);

        let mut sha_v = vec![0u8; dig.block_size()/2];
        let mut sha_bs = sha_v.borrow_mut();
        dig.input_str(&buf);
        dig.result(sha_bs);

        let mut res = sha_bs.to_vec();
        res.extend(salt.as_bytes().into_iter());
        res.to_base64(STANDARD)
    }

}

#[test]
fn test_encryptor() {
    let hello = "hello".to_string();
    let size = 6;

    let s1 = hello.sha1();
    assert!(!s1.is_empty());
    println!("sha1: {}", s1);

    let s256 = hello.sha256();
    assert!(!s256.is_empty());
    println!("sha256: {}", s256);

    let s512 = hello.sha512();
    assert!(!s512.is_empty());
    println!("sha512: {}", s512);

    let md5 = hello.md5();
    assert!(!md5.is_empty());
    println!("md5: {}", md5);

    let ss256 = hello.ssha256(size);
    assert!(!ss256.is_empty());
    println!("run: doveadm pw -t {}{} -p {}", "{SSHA256}", ss256, hello);

    let ss512 = hello.ssha512(size);
    assert!(!ss512.is_empty());
    println!("run: doveadm pw -t {}{} -p {}", "{SSHA512}", ss512, hello);
}
<commit_msg>add chk for sum<commit_after>extern crate rand;
extern crate crypto;
extern crate rustc_serialize;

use std::cmp::PartialEq;
use std::borrow::BorrowMut;
use std::iter::Extend;
use self::crypto::{sha1, sha2, md5, digest};
use self::rand::Rng;
use self::rustc_serialize::base64::{ToBase64, FromBase64, STANDARD};

pub trait Encryptor {

    fn sum_sha1(&self) -> String;
    fn chk_sha1(&self, s: &str) -> bool;
    fn sum_sha256(&self) -> String;
    fn chk_sha256(&self, s: &str) -> bool;
    fn sum_sha512(&self) -> String;
    fn chk_sha512(&self, s: &str) -> bool;
    fn sum_md5(&self) -> String;
    fn chk_md5(&self, s: &str) -> bool;

    fn sum_ssha512(&self, l: usize) -> String;
    fn chk_ssha512(&self, s: &str, l: usize) -> bool;
    fn sum_ssha256(&self, l: usize) -> String;
    fn chk_ssha256(&self, s: &str, l: usize) -> bool;

    fn sum<T: digest::Digest>(&self, dig: &mut T) -> String;
    fn ssum<T: digest::Digest>(&self, dig: &mut T, l: usize) -> String;
    fn schk<T: digest::Digest>(&self, dig: &mut T, s: &str, l: usize) -> bool;

}

impl Encryptor for String {

    fn sum_sha1(&self) -> String {
        let mut dig = sha1::Sha1::new();
        self.sum(&mut dig)
    }
    fn chk_sha1(&self, s: &str) -> bool {
        let d = s.to_string().sum_sha1();
        self.eq(&d)
    }
    fn sum_sha256(&self) -> String {
        let mut dig = sha2::Sha256::new();
        self.sum(&mut dig)
    }
    fn chk_sha256(&self, s: &str) -> bool {
        let d = s.to_string().sum_sha256();
        self.eq(&d)
    }
    fn sum_sha512(&self) -> String {
        let mut dig = sha2::Sha512::new();
        self.sum(&mut dig)
    }
    fn chk_sha512(&self, s: &str) -> bool {
        let d = s.to_string().sum_sha512();
        self.eq(&d)
    }
    fn sum_md5(&self) -> String {
        let mut dig = md5::Md5::new();
        self.sum(&mut dig)
    }
    fn chk_md5(&self, s: &str) -> bool {
        let d = s.to_string().sum_md5();
        self.eq(&d)
    }

    fn sum_ssha256(&self, l: usize) -> String {
        let mut dig = sha2::Sha256::new();
        self.ssum(&mut dig, l)
    }
    fn chk_ssha256(&self, s: &str, l: usize) -> bool{
        let mut dig = sha2::Sha256::new();
        self.schk(&mut dig, s, l)
    }
    fn sum_ssha512(&self, l: usize) -> String {
        let mut dig = sha2::Sha512::new();
        self.ssum(&mut dig, l)
    }
    fn chk_ssha512(&self, s: &str, l: usize) -> bool{
        let mut dig = sha2::Sha512::new();
        self.schk(&mut dig, s, l)
    }

    fn sum<T: digest::Digest>(&self, dig: &mut T) -> String {
        dig.input_str(&self);
        dig.result_str()
    }
    fn ssum<T: digest::Digest>(&self, dig: &mut T, l: usize) -> String {
        let salt: String = rand::thread_rng().gen_ascii_chars().take(l).collect();
        let mut buf = "".to_string();
        buf.push_str(&self);
        buf.push_str(&salt);

        let mut sha_v = vec![0u8; dig.block_size()/2];
        let mut sha_bs = sha_v.borrow_mut();
        dig.input_str(&buf);
        dig.result(sha_bs);

        let mut res = sha_bs.to_vec();
        res.extend(salt.as_bytes().into_iter());
        res.to_base64(STANDARD)
    }
    fn schk<T: digest::Digest>(&self, dig: &mut T, s: &str, l: usize) -> bool {
        match self.from_base64() {
            Ok(buf) => {
                let (sha, salt) = buf.split_at(buf.len()-l);
                let mut sha_v = vec![0u8; dig.block_size()/2];
                let mut sha_bs = sha_v.borrow_mut();

                dig.input_str(s);
                dig.input(salt);
                dig.result(sha_bs);

                sha == sha_bs
            },
            Err(_) => {
                false
            },
        }
    }

}

#[test]
fn test_encryptor() {
    let hello = "hello".to_string();
    let world = "world";
    let size = 6;

    let s1 = hello.sum_sha1();
    assert!(s1.chk_sha1(&hello));
    assert!(!s1.chk_sha1(world));
    println!("sha1: {}", s1);

    let s256 = hello.sum_sha256();
    assert!(s256.chk_sha256(&hello));
    assert!(!s256.chk_sha256(world));
    println!("sha256: {}", s256);

    let s512 = hello.sum_sha512();
    assert!(s512.chk_sha512(&hello));
    assert!(!s512.chk_sha512(world));
    println!("sha512: {}", s512);

    let smd5 = hello.sum_md5();
    assert!(smd5.chk_md5(&hello));
    assert!(!smd5.chk_md5(world));
    println!("md5: {}", smd5);

    let ss256 = hello.sum_ssha256(size);
    assert!(ss256.chk_ssha256(&hello, size));
    assert!(!ss256.chk_ssha256(world, size));
    println!("run: doveadm pw -t {}{} -p {}", "{SSHA256}", ss256, hello);

    let ss512 = hello.sum_ssha512(size);
    assert!(!ss512.is_empty());
    assert!(ss512.chk_ssha512(&hello, size));
    assert!(!ss512.chk_ssha512(world, size));
    println!("run: doveadm pw -t {}{} -p {}", "{SSHA512}", ss512, hello);
}
<|endoftext|>


<commit_before>
use std::ffi::CString;
use std::os::raw::c_char;

#[link( name = "ncurses" )]
extern {
    pub fn initscr();
    pub fn refresh();
    pub fn endwin();
    pub fn getch() -> i32;
    pub fn printw( format : *const c_char, ... );
    pub fn cbreak();
    pub fn noecho();
    pub fn keypad();
    pub fn clear();
}

extern {
    pub static error : i32;
    fn move_wrapper( y : i32, x : i32 );
}

pub unsafe fn cursor_move( y : i32, x : i32 ) {
    move_wrapper( y, x );
}

<commit_msg>added mvprintw to ncurses wrapper<commit_after>
use std::ffi::CString;
use std::os::raw::c_char;

#[link( name = "ncurses" )]
extern {
    pub fn initscr();
    pub fn refresh();
    pub fn endwin();
    pub fn getch() -> i32;
    pub fn printw( format : *const c_char, ... );
    pub fn cbreak();
    pub fn noecho();
    pub fn keypad();
    pub fn clear();
    pub fn mvprintw( y : i32, x : i32, format : *const c_char, ... );
}

extern {
    pub static error : i32;
    fn move_wrapper( y : i32, x : i32 );
}

pub unsafe fn cursor_move( y : i32, x : i32 ) {
    move_wrapper( y, x );
}

<|endoftext|>


<commit_before>use cocoa::base::{id, nil};
use cocoa::foundation::{NSUInteger, NSString};
use objc::runtime::{BOOL, NO, YES};
use objc::runtime::{Class, Object};
use sys::{MTLCreateSystemDefaultDevice, MTLCopyAllDevices, MTLDevice};
use std::borrow::Cow;
use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::ffi::CStr;
use {Size};

pub trait ReadOnlyDevice {
    fn is_headless(&self) -> bool;
    fn is_low_power(&self) -> bool;
    fn max_threads_per_group(&self) -> bool;
    fn get_name(&self) -> Cow<str>;
    fn supports_texture_sample_count(&self, sample_count: usize) -> bool;
}

pub struct Device(id);

impl Device {
    pub fn system_default_device() -> Result<Self, DeviceError> {
        let device = unsafe { MTLCreateSystemDefaultDevice() };
        if device != nil {
            Ok(Device(device))
        } else {
            Err(DeviceError::ConstructionFailed)
        }
    }

    pub fn enumerate_all_system_devices() -> Vec<Result<Self, DeviceError>> {
        let all_devices = unsafe { MTLCopyAllDevices() };
        let mut devices_vec = vec![];

        devices_vec
    }

    pub unsafe fn into_raw(self) -> id {
        self.0
    }

    pub unsafe fn from_raw_unchecked(device_ptr: id) -> Self {
        Device(device_ptr)
    }

    pub fn from_raw(device_ptr: id) -> Result<Self, DeviceError> {
        #[link(name = "Foundation", kind = "framework")]
        extern {
            fn NSProtocolFromString(namestr: id) -> id;
        }

        let conforms_to_protocol: BOOL = unsafe {
            let mtl_device_protocol_str = NSString::alloc(nil).init_str("MTLDevice");
            let mtl_device_protocol = NSProtocolFromString(mtl_device_protocol_str);
            msg_send![device_ptr, conformsToProtocol:mtl_device_protocol]
        };

        if device_ptr == nil {
            Err(DeviceError::ConstructedFromNil)
        } else if conforms_to_protocol == NO {
            Err(DeviceError::ConstructedFromWrongPointerType)
        } else {
            Ok(Device(device_ptr))
        }
    }

    pub fn is_headless(&self) -> bool {
        unsafe { self.0.headless() == YES }
    }

    pub fn is_low_power(&self) -> bool {
        unsafe { self.0.lowPower() == YES }
    }

    pub fn max_threads_per_group(&self) -> Size {
        unsafe { self.0.maxThreadsPerGroup().into() }
    }

    pub fn get_name(&self) -> Cow<str> {
        unsafe { CStr::from_ptr(self.0.name().UTF8String()).to_string_lossy() }
    }

    pub fn supports_texture_sample_count(&self, sample_count: usize) -> bool {
        unsafe { self.0.supportsTextureSampleCount(sample_count as NSUInteger) == YES }
    }
}

/// Internal utility function to get a Device's id without consuming it.
/// Not exported publicly from this crate.
#[doc(hidden)]
pub unsafe fn _device_get_raw(device: &Device) -> id {
    device.0
}

#[derive(Clone, Debug)]
pub enum DeviceError {
    ConstructionFailed,
    ConstructedFromNil,
    ConstructedFromWrongPointerType,
    OtherRuntimeError
}

impl Display for DeviceError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let descr = match *self {
            DeviceError::ConstructionFailed => "DeviceError::ConstructionFailed",
            DeviceError::ConstructedFromNil => "DeviceError::ConstructedFromNil",
            DeviceError::ConstructedFromWrongPointerType => "DeviceError::ConstructedFromWrongPointerType",
            DeviceError::OtherRuntimeError => "DeviceError::OtherRuntimeError"
        };
        write!(f, "{}", descr)
    }
}

impl Error for DeviceError {
    fn description(&self) -> &str {
        match *self {
            DeviceError::ConstructionFailed =>
                "Could not create a default device. Please ensure that you are using at least OSX 10.11 or iOS 8.0",
            DeviceError::ConstructedFromNil => "Attempted to create a device from a nil pointer",
            DeviceError::ConstructedFromWrongPointerType =>
                "Attempted to create a device from a pointer which does not implement MTLDevice",
            DeviceError::OtherRuntimeError => "An error occured in the Objective-C runtime"
        }
    }
}
<commit_msg>Fix warnings by removing unused imports and adding allow(unused_mut, unused_variables) annotation to `Device::enumerate_all_system_devices`<commit_after>use cocoa::base::{id, nil};
use cocoa::foundation::{NSUInteger, NSString};
use objc::runtime::{BOOL, NO, YES};
use sys::{MTLCreateSystemDefaultDevice, MTLCopyAllDevices, MTLDevice};
use std::borrow::Cow;
use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::ffi::CStr;
use {Size};

pub trait ReadOnlyDevice {
    fn is_headless(&self) -> bool;
    fn is_low_power(&self) -> bool;
    fn max_threads_per_group(&self) -> bool;
    fn get_name(&self) -> Cow<str>;
    fn supports_texture_sample_count(&self, sample_count: usize) -> bool;
}

pub struct Device(id);

impl Device {
    pub fn system_default_device() -> Result<Self, DeviceError> {
        let device = unsafe { MTLCreateSystemDefaultDevice() };
        if device != nil {
            Ok(Device(device))
        } else {
            Err(DeviceError::ConstructionFailed)
        }
    }

    #[allow(unused_mut, unused_variables)]
    pub fn enumerate_all_system_devices() -> Vec<Result<Self, DeviceError>> {
        let all_devices = unsafe { MTLCopyAllDevices() };
        let mut devices_vec = vec![];

        devices_vec
    }

    pub unsafe fn into_raw(self) -> id {
        self.0
    }

    pub unsafe fn from_raw_unchecked(device_ptr: id) -> Self {
        Device(device_ptr)
    }

    pub fn from_raw(device_ptr: id) -> Result<Self, DeviceError> {
        #[link(name = "Foundation", kind = "framework")]
        extern {
            fn NSProtocolFromString(namestr: id) -> id;
        }

        let conforms_to_protocol: BOOL = unsafe {
            let mtl_device_protocol_str = NSString::alloc(nil).init_str("MTLDevice");
            let mtl_device_protocol = NSProtocolFromString(mtl_device_protocol_str);
            msg_send![device_ptr, conformsToProtocol:mtl_device_protocol]
        };

        if device_ptr == nil {
            Err(DeviceError::ConstructedFromNil)
        } else if conforms_to_protocol == NO {
            Err(DeviceError::ConstructedFromWrongPointerType)
        } else {
            Ok(Device(device_ptr))
        }
    }

    pub fn is_headless(&self) -> bool {
        unsafe { self.0.headless() == YES }
    }

    pub fn is_low_power(&self) -> bool {
        unsafe { self.0.lowPower() == YES }
    }

    pub fn max_threads_per_group(&self) -> Size {
        unsafe { self.0.maxThreadsPerGroup().into() }
    }

    pub fn get_name(&self) -> Cow<str> {
        unsafe { CStr::from_ptr(self.0.name().UTF8String()).to_string_lossy() }
    }

    pub fn supports_texture_sample_count(&self, sample_count: usize) -> bool {
        unsafe { self.0.supportsTextureSampleCount(sample_count as NSUInteger) == YES }
    }
}

/// Internal utility function to get a Device's id without consuming it.
/// Not exported publicly from this crate.
#[doc(hidden)]
pub unsafe fn _device_get_raw(device: &Device) -> id {
    device.0
}

#[derive(Clone, Debug)]
pub enum DeviceError {
    ConstructionFailed,
    ConstructedFromNil,
    ConstructedFromWrongPointerType,
    OtherRuntimeError
}

impl Display for DeviceError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let descr = match *self {
            DeviceError::ConstructionFailed => "DeviceError::ConstructionFailed",
            DeviceError::ConstructedFromNil => "DeviceError::ConstructedFromNil",
            DeviceError::ConstructedFromWrongPointerType => "DeviceError::ConstructedFromWrongPointerType",
            DeviceError::OtherRuntimeError => "DeviceError::OtherRuntimeError"
        };
        write!(f, "{}", descr)
    }
}

impl Error for DeviceError {
    fn description(&self) -> &str {
        match *self {
            DeviceError::ConstructionFailed =>
                "Could not create a default device. Please ensure that you are using at least OSX 10.11 or iOS 8.0",
            DeviceError::ConstructedFromNil => "Attempted to create a device from a nil pointer",
            DeviceError::ConstructedFromWrongPointerType =>
                "Attempted to create a device from a pointer which does not implement MTLDevice",
            DeviceError::OtherRuntimeError => "An error occured in the Objective-C runtime"
        }
    }
}
<|endoftext|>


<commit_before>use std::io;

use actix_connect::resolver::ResolveError;
use derive_more::{Display, From};

#[cfg(feature = "openssl")]
use actix_connect::ssl::openssl::{HandshakeError, SslError};

use crate::error::{Error, ParseError, ResponseError};
use crate::http::{Error as HttpError, StatusCode};

/// A set of errors that can occur while connecting to an HTTP host
#[derive(Debug, Display, From)]
pub enum ConnectError {
    /// SSL feature is not enabled
    #[display(fmt = "SSL is not supported")]
    SslIsNotSupported,

    /// SSL error
    #[cfg(feature = "openssl")]
    #[display(fmt = "{}", _0)]
    SslError(SslError),

    /// SSL Handshake error
    #[cfg(feature = "openssl")]
    #[display(fmt = "{}", _0)]
    SslHandshakeError(String),

    /// Failed to resolve the hostname
    #[display(fmt = "Failed resolving hostname: {}", _0)]
    Resolver(ResolveError),

    /// No dns records
    #[display(fmt = "No dns records found for the input")]
    NoRecords,

    /// Http2 error
    #[display(fmt = "{}", _0)]
    H2(h2::Error),

    /// Connecting took too long
    #[display(fmt = "Timeout out while establishing connection")]
    Timeout,

    /// Connector has been disconnected
    #[display(fmt = "Internal error: connector has been disconnected")]
    Disconnected,

    /// Unresolved host name
    #[display(fmt = "Connector received `Connect` method with unresolved host")]
    Unresolved,

    /// Connection io error
    #[display(fmt = "{}", _0)]
    Io(io::Error),
}

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

impl From<actix_connect::ConnectError> for ConnectError {
    fn from(err: actix_connect::ConnectError) -> ConnectError {
        match err {
            actix_connect::ConnectError::Resolver(e) => ConnectError::Resolver(e),
            actix_connect::ConnectError::NoRecords => ConnectError::NoRecords,
            actix_connect::ConnectError::InvalidInput => panic!(),
            actix_connect::ConnectError::Unresolved => ConnectError::Unresolved,
            actix_connect::ConnectError::Io(e) => ConnectError::Io(e),
        }
    }
}

#[cfg(feature = "openssl")]
impl<T: std::fmt::Debug> From<HandshakeError<T>> for ConnectError {
    fn from(err: HandshakeError<T>) -> ConnectError {
        ConnectError::SslHandshakeError(format!("{:?}", err))
    }
}

#[derive(Debug, Display, From)]
pub enum InvalidUrl {
    #[display(fmt = "Missing url scheme")]
    MissingScheme,
    #[display(fmt = "Unknown url scheme")]
    UnknownScheme,
    #[display(fmt = "Missing host name")]
    MissingHost,
    #[display(fmt = "Url parse error: {}", _0)]
    HttpError(http::Error),
}

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

/// A set of errors that can occur during request sending and response reading
#[derive(Debug, Display, From)]
pub enum SendRequestError {
    /// Invalid URL
    #[display(fmt = "Invalid URL: {}", _0)]
    Url(InvalidUrl),
    /// Failed to connect to host
    #[display(fmt = "Failed to connect to host: {}", _0)]
    Connect(ConnectError),
    /// Error sending request
    Send(io::Error),
    /// Error parsing response
    Response(ParseError),
    /// Http error
    #[display(fmt = "{}", _0)]
    Http(HttpError),
    /// Http2 error
    #[display(fmt = "{}", _0)]
    H2(h2::Error),
    /// Response took too long
    #[display(fmt = "Timeout out while waiting for response")]
    Timeout,
    /// Tunnels are not supported for http2 connection
    #[display(fmt = "Tunnels are not supported for http2 connection")]
    TunnelNotSupported,
    /// Error sending request body
    Body(Error),
}

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

/// Convert `SendRequestError` to a server `Response`
impl ResponseError for SendRequestError {
    fn status_code(&self) -> StatusCode {
        match *self {
            SendRequestError::Connect(ConnectError::Timeout) => {
                StatusCode::GATEWAY_TIMEOUT
            }
            SendRequestError::Connect(_) => StatusCode::BAD_REQUEST,
            _ => StatusCode::INTERNAL_SERVER_ERROR,
        }
    }
}

/// A set of errors that can occur during freezing a request
#[derive(Debug, Display, From)]
pub enum FreezeRequestError {
    /// Invalid URL
    #[display(fmt = "Invalid URL: {}", _0)]
    Url(InvalidUrl),
    /// Http error
    #[display(fmt = "{}", _0)]
    Http(HttpError),
}

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

impl From<FreezeRequestError> for SendRequestError {
    fn from(e: FreezeRequestError) -> Self {
        match e {
            FreezeRequestError::Url(e) => e.into(),
            FreezeRequestError::Http(e) => e.into(),
        }
    }
}
<commit_msg>Fix typo in timeout error display (#1552)<commit_after>use std::io;

use actix_connect::resolver::ResolveError;
use derive_more::{Display, From};

#[cfg(feature = "openssl")]
use actix_connect::ssl::openssl::{HandshakeError, SslError};

use crate::error::{Error, ParseError, ResponseError};
use crate::http::{Error as HttpError, StatusCode};

/// A set of errors that can occur while connecting to an HTTP host
#[derive(Debug, Display, From)]
pub enum ConnectError {
    /// SSL feature is not enabled
    #[display(fmt = "SSL is not supported")]
    SslIsNotSupported,

    /// SSL error
    #[cfg(feature = "openssl")]
    #[display(fmt = "{}", _0)]
    SslError(SslError),

    /// SSL Handshake error
    #[cfg(feature = "openssl")]
    #[display(fmt = "{}", _0)]
    SslHandshakeError(String),

    /// Failed to resolve the hostname
    #[display(fmt = "Failed resolving hostname: {}", _0)]
    Resolver(ResolveError),

    /// No dns records
    #[display(fmt = "No dns records found for the input")]
    NoRecords,

    /// Http2 error
    #[display(fmt = "{}", _0)]
    H2(h2::Error),

    /// Connecting took too long
    #[display(fmt = "Timeout while establishing connection")]
    Timeout,

    /// Connector has been disconnected
    #[display(fmt = "Internal error: connector has been disconnected")]
    Disconnected,

    /// Unresolved host name
    #[display(fmt = "Connector received `Connect` method with unresolved host")]
    Unresolved,

    /// Connection io error
    #[display(fmt = "{}", _0)]
    Io(io::Error),
}

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

impl From<actix_connect::ConnectError> for ConnectError {
    fn from(err: actix_connect::ConnectError) -> ConnectError {
        match err {
            actix_connect::ConnectError::Resolver(e) => ConnectError::Resolver(e),
            actix_connect::ConnectError::NoRecords => ConnectError::NoRecords,
            actix_connect::ConnectError::InvalidInput => panic!(),
            actix_connect::ConnectError::Unresolved => ConnectError::Unresolved,
            actix_connect::ConnectError::Io(e) => ConnectError::Io(e),
        }
    }
}

#[cfg(feature = "openssl")]
impl<T: std::fmt::Debug> From<HandshakeError<T>> for ConnectError {
    fn from(err: HandshakeError<T>) -> ConnectError {
        ConnectError::SslHandshakeError(format!("{:?}", err))
    }
}

#[derive(Debug, Display, From)]
pub enum InvalidUrl {
    #[display(fmt = "Missing url scheme")]
    MissingScheme,
    #[display(fmt = "Unknown url scheme")]
    UnknownScheme,
    #[display(fmt = "Missing host name")]
    MissingHost,
    #[display(fmt = "Url parse error: {}", _0)]
    HttpError(http::Error),
}

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

/// A set of errors that can occur during request sending and response reading
#[derive(Debug, Display, From)]
pub enum SendRequestError {
    /// Invalid URL
    #[display(fmt = "Invalid URL: {}", _0)]
    Url(InvalidUrl),
    /// Failed to connect to host
    #[display(fmt = "Failed to connect to host: {}", _0)]
    Connect(ConnectError),
    /// Error sending request
    Send(io::Error),
    /// Error parsing response
    Response(ParseError),
    /// Http error
    #[display(fmt = "{}", _0)]
    Http(HttpError),
    /// Http2 error
    #[display(fmt = "{}", _0)]
    H2(h2::Error),
    /// Response took too long
    #[display(fmt = "Timeout while waiting for response")]
    Timeout,
    /// Tunnels are not supported for http2 connection
    #[display(fmt = "Tunnels are not supported for http2 connection")]
    TunnelNotSupported,
    /// Error sending request body
    Body(Error),
}

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

/// Convert `SendRequestError` to a server `Response`
impl ResponseError for SendRequestError {
    fn status_code(&self) -> StatusCode {
        match *self {
            SendRequestError::Connect(ConnectError::Timeout) => {
                StatusCode::GATEWAY_TIMEOUT
            }
            SendRequestError::Connect(_) => StatusCode::BAD_REQUEST,
            _ => StatusCode::INTERNAL_SERVER_ERROR,
        }
    }
}

/// A set of errors that can occur during freezing a request
#[derive(Debug, Display, From)]
pub enum FreezeRequestError {
    /// Invalid URL
    #[display(fmt = "Invalid URL: {}", _0)]
    Url(InvalidUrl),
    /// Http error
    #[display(fmt = "{}", _0)]
    Http(HttpError),
}

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

impl From<FreezeRequestError> for SendRequestError {
    fn from(e: FreezeRequestError) -> Self {
        match e {
            FreezeRequestError::Url(e) => e.into(),
            FreezeRequestError::Http(e) => e.into(),
        }
    }
}
<|endoftext|>


<commit_before>//! This pass replaces a drop of a type that does not need dropping, with a goto

use crate::transform::{MirPass, MirSource};
use rustc_hir::def_id::LocalDefId;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;

pub struct RemoveUnneededDrops {
    def_id: LocalDefId,
}

impl RemoveUnneededDrops {
    pub fn new(def_id: LocalDefId) -> Self {
        Self { def_id }
    }
}

impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
        trace!("Running SimplifyComparisonIntegral on {:?}", source);
        let mut opt_finder = RemoveUnneededDropsOptimizationFinder {
            tcx,
            body,
            optimizations: vec![],
            def_id: self.def_id,
        };
        opt_finder.visit_body(body);
        for (loc, target) in opt_finder.optimizations {
            let terminator = body.basic_blocks_mut()[loc.block].terminator_mut();
            debug!("SUCCESS: replacing `drop` with goto({:?})", target);
            terminator.kind = TerminatorKind::Goto { target };
        }
    }
}

impl<'a, 'tcx> Visitor<'tcx> for RemoveUnneededDropsOptimizationFinder<'a, 'tcx> {
    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
        match terminator.kind {
            TerminatorKind::Drop { place, target, .. } => {
                let ty = place.ty(self.body, self.tcx);
                let needs_drop = ty.ty.needs_drop(self.tcx, self.tcx.param_env(self.def_id));
                if !needs_drop {
                    self.optimizations.push((location, target));
                }
            }
            _ => {}
        }
        self.super_terminator(terminator, location);
    }
}
pub struct RemoveUnneededDropsOptimizationFinder<'a, 'tcx> {
    tcx: TyCtxt<'tcx>,
    body: &'a Body<'tcx>,
    optimizations: Vec<(Location, BasicBlock)>,
    def_id: LocalDefId,
}
<commit_msg>Suggestion from review<commit_after>//! This pass replaces a drop of a type that does not need dropping, with a goto

use crate::transform::{MirPass, MirSource};
use rustc_hir::def_id::LocalDefId;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;

pub struct RemoveUnneededDrops {
    def_id: LocalDefId,
}

impl RemoveUnneededDrops {
    pub fn new(def_id: LocalDefId) -> Self {
        Self { def_id }
    }
}

impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
        trace!("Running RemoveUnneededDrops on {:?}", source);
        let mut opt_finder = RemoveUnneededDropsOptimizationFinder {
            tcx,
            body,
            optimizations: vec![],
            def_id: self.def_id,
        };
        opt_finder.visit_body(body);
        for (loc, target) in opt_finder.optimizations {
            let terminator = body.basic_blocks_mut()[loc.block].terminator_mut();
            debug!("SUCCESS: replacing `drop` with goto({:?})", target);
            terminator.kind = TerminatorKind::Goto { target };
        }
    }
}

impl<'a, 'tcx> Visitor<'tcx> for RemoveUnneededDropsOptimizationFinder<'a, 'tcx> {
    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
        match terminator.kind {
            TerminatorKind::Drop { place, target, .. } => {
                let ty = place.ty(self.body, self.tcx);
                let needs_drop = ty.ty.needs_drop(self.tcx, self.tcx.param_env(self.def_id));
                if !needs_drop {
                    self.optimizations.push((location, target));
                }
            }
            _ => {}
        }
        self.super_terminator(terminator, location);
    }
}
pub struct RemoveUnneededDropsOptimizationFinder<'a, 'tcx> {
    tcx: TyCtxt<'tcx>,
    body: &'a Body<'tcx>,
    optimizations: Vec<(Location, BasicBlock)>,
    def_id: LocalDefId,
}
<|endoftext|>


<commit_before>
use BuildQuery;
use Groups;

// https://docs.gitlab.com/ce/api/groups.html
// List groups:                 GET /groups
// List owned groups:           GET /groups/owned
// List a group's projects:     GET /groups/:id/projects
// Details of a group:          GET /groups/:id
// New group:                   POST /groups
// Transfer project to group:   POST  /groups/:id/projects/:project_id
// Update group:                PUT /groups/:id
// Remove group:                DELETE /groups/:id
// Search for group:            GET /groups?search=foobar

// https://docs.gitlab.com/ce/api/groups.html#list-groups

#[derive(Debug, Copy, Clone)]
pub enum GroupListerOptionsOrderBy {
    Name,
    Path,
}

// impl Default for GroupListerOptionsOrderBy {
//     fn default() -> GroupListerOptionsOrderBy { GroupListerOptionsOrderBy::Name }
// }

#[derive(Debug, Copy, Clone)]
pub enum GroupListerOptionsSort {
    Asc,
    Desc,
}

// impl Default for GroupListerOptionsSort {
//     fn default() -> GroupListerOptionsSort { GroupListerOptionsSort::Asc }
// }

fn append_group_lister_options_order_by(order_by: GroupListerOptionsOrderBy, s: &mut String) {
    s.push_str(match order_by {
        GroupListerOptionsOrderBy::Name => "name",
        GroupListerOptionsOrderBy::Path => "path",
    });
}

fn append_group_lister_options_sort(order_by: GroupListerOptionsSort, s: &mut String) {
    s.push_str(match order_by {
        GroupListerOptionsSort::Asc => "asc",
        GroupListerOptionsSort::Desc => "desc",
    });
}

/// https://docs.gitlab.com/ce/api/groups.html#list-groups
#[derive(Default, Debug, Clone)]
pub struct Listing {
    /// Skip the group IDs passes
    skip_groups: Vec<i64>,
    /// Show all the groups you have access to
    all_available: Option<bool>,
    /// Return list of authorized groups matching the search criteria
    search: String,
    /// Order groups by `name` or `path`. Default is `name`
    order_by: Option<GroupListerOptionsOrderBy>,
    /// Order groups in `asc` or `desc` order. Default is `asc`
    sort: Option<GroupListerOptionsSort>,
}

impl Listing {
    pub fn new() -> Listing {
        Default::default()
    }
    pub fn skip_groups(&mut self, skip_groups: Vec<i64>) -> &mut Listing {
        self.skip_groups = skip_groups;
        self
    }
    pub fn all_available(&mut self, all_available: bool) -> &mut Listing {
        self.all_available = Some(all_available);
        self
    }
    pub fn search(&mut self, search: String) -> &mut Listing {
        self.search = search;
        self
    }
    pub fn order_by(&mut self, order_by: GroupListerOptionsOrderBy) -> &mut Listing {
        self.order_by = Some(order_by);
        self
    }
    fn sort(&mut self, sort: GroupListerOptionsSort) -> &mut Listing {
        self.sort = Some(sort);
        self
    }
}

impl BuildQuery for Listing {
    fn build_query(&self) -> String {

        let mut query = String::from("groups");

        let amp_char = "&";
        let none_char = "";
        let mut split_char = &none_char;

        // Append a "?", only if one of the `Option` is `Some(_)`
        query.push_str(match (self.skip_groups.is_empty(),
                              &self.all_available,
                              self.search.is_empty(),
                              &self.order_by,
                              &self.sort) {
            (true, &None, true, &None, &None) => "",
            _ => "?",
        });

        if !self.skip_groups.is_empty() {
            query.push_str(&split_char);
            split_char = &amp_char;

            let mut array_split_char = &none_char;
            for skip_group in &self.skip_groups {
                query.push_str(array_split_char);
                query.push_str("skip_groups[]=");
                query.push_str(&skip_group.to_string());
                array_split_char = &amp_char;
            }
        }

        self.all_available.map(|all_available| {
            query.push_str(&split_char);
            split_char = &amp_char;

            if all_available {
                query.push_str("all_available=true")
            } else {
                query.push_str("all_available=false")
            }
        });

        if !self.search.is_empty() {
            query.push_str(&split_char);
            split_char = &amp_char;

            query.push_str("search=");
            query.push_str(&self.search);
        }

        self.order_by.map(|order_by| {
            query.push_str(&split_char);
            split_char = &amp_char;

            query.push_str("order_by=");
            append_group_lister_options_order_by(order_by, &mut query);
        });

        self.sort.map(|sort| {
            query.push_str(&split_char);
            split_char = &amp_char;

            query.push_str("sort=");
            append_group_lister_options_sort(sort, &mut query);
        });

        query
    }
}

#[test]
fn test_append_group_lister_options_order_by() {
    let expected_string = "Initialnamepathpathname";

    let mut s = String::from("Initial");

    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Name, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Path, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Path, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Name, &mut s);

    assert_eq!(s, expected_string);
}

#[test]
fn test_append_group_lister_options_sort() {
    let expected_string = "Initialascdescascdesc";

    let mut s = String::from("Initial");

    append_group_lister_options_sort(GroupListerOptionsSort::Asc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Desc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Asc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Desc, &mut s);

    assert_eq!(s, expected_string);
}

#[test]
fn groups_build_query_default() {
    let expected_string = "groups";
    let listing: Listing = Default::default();
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups";
    let listing = Listing::new();
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_skip_groups() {
    let expected_string = "groups?skip_groups[]=1&skip_groups[]=2&skip_groups[]=3";
    let query = Listing::new().skip_groups(vec![1,2,3]).build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_all_available() {
    let expected_string = "groups?all_available=true";
    let query = Listing::new().all_available(true).build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups?all_available=false";
    let query = Listing::new().all_available(false).build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_search() {
    let expected_string = "groups?search=SearchPattern";
    let query = Listing::new().search(String::from("SearchPattern")).build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_order_by_name() {
    let expected_string = "groups?order_by=name";
    let query = Listing::new().order_by(GroupListerOptionsOrderBy::Name).build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_order_by_path() {
    let expected_string = "groups?order_by=path";
    let query = Listing::new().order_by(GroupListerOptionsOrderBy::Path).build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_sort() {
    let expected_string = "groups?sort=asc";
    let query = Listing::new().sort(GroupListerOptionsSort::Asc).build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups?sort=desc";
    let query = Listing::new().sort(GroupListerOptionsSort::Desc).build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_search_order_by_path() {
    let expected_string = "groups?search=SearchPattern&order_by=path";
    let query = Listing::new().order_by(GroupListerOptionsOrderBy::Path).search(String::from("SearchPattern")).build_query();
    assert_eq!(query, expected_string);
    let query = Listing::new().search(String::from("SearchPattern")).order_by(GroupListerOptionsOrderBy::Path).build_query();
    assert_eq!(query, expected_string);
}
<commit_msg>Rename `GroupListerOptionsOrderBy` to `ListingOrderBy`<commit_after>
use BuildQuery;
use Groups;

// https://docs.gitlab.com/ce/api/groups.html
// List groups:                 GET /groups
// List owned groups:           GET /groups/owned
// List a group's projects:     GET /groups/:id/projects
// Details of a group:          GET /groups/:id
// New group:                   POST /groups
// Transfer project to group:   POST  /groups/:id/projects/:project_id
// Update group:                PUT /groups/:id
// Remove group:                DELETE /groups/:id
// Search for group:            GET /groups?search=foobar

// https://docs.gitlab.com/ce/api/groups.html#list-groups

#[derive(Debug, Copy, Clone)]
pub enum ListingOrderBy {
    Name,
    Path,
}

// impl Default for ListingOrderBy {
//     fn default() -> ListingOrderBy { ListingOrderBy::Name }
// }

#[derive(Debug, Copy, Clone)]
pub enum GroupListerOptionsSort {
    Asc,
    Desc,
}

// impl Default for GroupListerOptionsSort {
//     fn default() -> GroupListerOptionsSort { GroupListerOptionsSort::Asc }
// }

fn append_group_lister_options_order_by(order_by: ListingOrderBy, s: &mut String) {
    s.push_str(match order_by {
        ListingOrderBy::Name => "name",
        ListingOrderBy::Path => "path",
    });
}

fn append_group_lister_options_sort(order_by: GroupListerOptionsSort, s: &mut String) {
    s.push_str(match order_by {
        GroupListerOptionsSort::Asc => "asc",
        GroupListerOptionsSort::Desc => "desc",
    });
}

/// https://docs.gitlab.com/ce/api/groups.html#list-groups
#[derive(Default, Debug, Clone)]
pub struct Listing {
    /// Skip the group IDs passes
    skip_groups: Vec<i64>,
    /// Show all the groups you have access to
    all_available: Option<bool>,
    /// Return list of authorized groups matching the search criteria
    search: String,
    /// Order groups by `name` or `path`. Default is `name`
    order_by: Option<ListingOrderBy>,
    /// Order groups in `asc` or `desc` order. Default is `asc`
    sort: Option<GroupListerOptionsSort>,
}

impl Listing {
    pub fn new() -> Listing {
        Default::default()
    }
    pub fn skip_groups(&mut self, skip_groups: Vec<i64>) -> &mut Listing {
        self.skip_groups = skip_groups;
        self
    }
    pub fn all_available(&mut self, all_available: bool) -> &mut Listing {
        self.all_available = Some(all_available);
        self
    }
    pub fn search(&mut self, search: String) -> &mut Listing {
        self.search = search;
        self
    }
    pub fn order_by(&mut self, order_by: ListingOrderBy) -> &mut Listing {
        self.order_by = Some(order_by);
        self
    }
    fn sort(&mut self, sort: GroupListerOptionsSort) -> &mut Listing {
        self.sort = Some(sort);
        self
    }
}

impl BuildQuery for Listing {
    fn build_query(&self) -> String {

        let mut query = String::from("groups");

        let amp_char = "&";
        let none_char = "";
        let mut split_char = &none_char;

        // Append a "?", only if one of the `Option` is `Some(_)`
        query.push_str(match (self.skip_groups.is_empty(),
                              &self.all_available,
                              self.search.is_empty(),
                              &self.order_by,
                              &self.sort) {
            (true, &None, true, &None, &None) => "",
            _ => "?",
        });

        if !self.skip_groups.is_empty() {
            query.push_str(&split_char);
            split_char = &amp_char;

            let mut array_split_char = &none_char;
            for skip_group in &self.skip_groups {
                query.push_str(array_split_char);
                query.push_str("skip_groups[]=");
                query.push_str(&skip_group.to_string());
                array_split_char = &amp_char;
            }
        }

        self.all_available.map(|all_available| {
            query.push_str(&split_char);
            split_char = &amp_char;

            if all_available {
                query.push_str("all_available=true")
            } else {
                query.push_str("all_available=false")
            }
        });

        if !self.search.is_empty() {
            query.push_str(&split_char);
            split_char = &amp_char;

            query.push_str("search=");
            query.push_str(&self.search);
        }

        self.order_by.map(|order_by| {
            query.push_str(&split_char);
            split_char = &amp_char;

            query.push_str("order_by=");
            append_group_lister_options_order_by(order_by, &mut query);
        });

        self.sort.map(|sort| {
            query.push_str(&split_char);
            split_char = &amp_char;

            query.push_str("sort=");
            append_group_lister_options_sort(sort, &mut query);
        });

        query
    }
}

#[test]
fn test_append_group_lister_options_order_by() {
    let expected_string = "Initialnamepathpathname";

    let mut s = String::from("Initial");

    append_group_lister_options_order_by(ListingOrderBy::Name, &mut s);
    append_group_lister_options_order_by(ListingOrderBy::Path, &mut s);
    append_group_lister_options_order_by(ListingOrderBy::Path, &mut s);
    append_group_lister_options_order_by(ListingOrderBy::Name, &mut s);

    assert_eq!(s, expected_string);
}

#[test]
fn test_append_group_lister_options_sort() {
    let expected_string = "Initialascdescascdesc";

    let mut s = String::from("Initial");

    append_group_lister_options_sort(GroupListerOptionsSort::Asc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Desc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Asc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Desc, &mut s);

    assert_eq!(s, expected_string);
}

#[test]
fn groups_build_query_default() {
    let expected_string = "groups";
    let listing: Listing = Default::default();
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups";
    let listing = Listing::new();
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_skip_groups() {
    let expected_string = "groups?skip_groups[]=1&skip_groups[]=2&skip_groups[]=3";
    let query = Listing::new().skip_groups(vec![1,2,3]).build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_all_available() {
    let expected_string = "groups?all_available=true";
    let query = Listing::new().all_available(true).build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups?all_available=false";
    let query = Listing::new().all_available(false).build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_search() {
    let expected_string = "groups?search=SearchPattern";
    let query = Listing::new().search(String::from("SearchPattern")).build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_order_by_name() {
    let expected_string = "groups?order_by=name";
    let query = Listing::new().order_by(ListingOrderBy::Name).build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_order_by_path() {
    let expected_string = "groups?order_by=path";
    let query = Listing::new().order_by(ListingOrderBy::Path).build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_sort() {
    let expected_string = "groups?sort=asc";
    let query = Listing::new().sort(GroupListerOptionsSort::Asc).build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups?sort=desc";
    let query = Listing::new().sort(GroupListerOptionsSort::Desc).build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_search_order_by_path() {
    let expected_string = "groups?search=SearchPattern&order_by=path";
    let query = Listing::new().order_by(ListingOrderBy::Path).search(String::from("SearchPattern")).build_query();
    assert_eq!(query, expected_string);
    let query = Listing::new().search(String::from("SearchPattern")).order_by(ListingOrderBy::Path).build_query();
    assert_eq!(query, expected_string);
}
<|endoftext|>