<commit_before>//
// MSX CAS Packager
// Copyright (c) 2015 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::f32;
use std::convert::From;
use std::io::Write;
use std::io::Error as IoError;
use std::iter::FromIterator;
use std::result;

use byteorder::{LittleEndian, WriteBytesExt};

const SHORT_PULSE: u32 = 2400;
const LONG_PULSE: u32 = 1200;

const SHORT_HEADER: u32 = 4000;
const LONG_HEADER: u32 = 16000;

pub enum Error {
	Io(IoError)
}

impl From<IoError> for Error {
	fn from(e: IoError) -> Error { Error::Io(e) }
}

type Result<T> = result::Result<T, Error>;

/// An object capable to export binary data in WAV format
///
/// The exporter object works by encoding silences, headers and data into
/// an internal buffer. When all the necessary data is encoded, you may use
/// the `export()` method to generate the corresponding WAV header and dump
/// the content into a valid WAV file.
pub struct Exporter {
	bauds: u32,
	sample_rate: u32,
	buffer: Vec<u8>,
}

impl Exporter {

	/// Create a new exporter using default settings
	///
	/// Default settins are 1200 bauds and 43200 samples per second.
	pub fn new() -> Exporter {
		Exporter {
			bauds: 1200,
			sample_rate: 43200,
			buffer: Vec::new(),
		}
	}

	/// Export the encoded data to the given `Write` instance
	///
	/// This method dumps the encoded data into the given `Write` instance. Before
	/// calling this method, you must use the `write_X()` functions to encode
	/// some data.
	pub fn export<W: Write>(&self, w: &mut W) -> Result<()> {
		try!(self.write_wave(w));
		try!(w.write(&*self.buffer));
		Ok(())
	}

	/// Write a short header to the internal buffer
	pub fn write_short_header(&mut self) -> Result<usize> {
		self.write_header(SHORT_HEADER)
	}

	/// Write a long header to the internal buffer
	pub fn write_long_header(&mut self) -> Result<usize> {
		self.write_header(LONG_HEADER)
	}

	/// Write a header comprised by the given amount of pulses to the internal buffer
	pub fn write_header(&mut self, pulses: u32) -> Result<usize> {
		let to = pulses * self.bauds / 1200;
		let mut nbytes = 0;
		for _ in 0..to {
			nbytes += try!(self.write_pulse(SHORT_PULSE));
		}
		Ok(nbytes)
	}

	/// Write a short silence (1 second) to the internal buffer
	pub fn write_short_silence(&mut self) -> Result<usize> {
		let pulses = self.sample_rate;
		self.write_silence(pulses)
	}

	/// Write a long silence (2 seconds) to the internal buffer
	pub fn write_long_silence(&mut self) -> Result<usize> {
		let pulses = self.sample_rate * 2;
		self.write_silence(pulses)
	}

	/// Write a silence comprised by the given amount of pulses to the internal buffer
	pub fn write_silence(&mut self, pulses: u32) ->  Result<usize> {
		let mut nbytes = 0;
		for _ in 0..pulses {
			nbytes += try!(self.buffer.write(&[0x80]).map_err(Error::from));
		}
		Ok(nbytes)
	}

	/// Write binary data to the internal buffer
	pub fn write_data(&mut self, data: &[u8]) -> Result<usize> {
		let mut nbytes = 0;
		for byte in data {
			nbytes += try!(self.write_byte(*byte));
		}
		Ok(nbytes)
	}

	fn write_wave<W: Write>(&self, w: &mut W) -> Result<()> {
		let data_len = self.buffer.len() as u32;
		let file_len = data_len + 44;

		// RIFF chunk start
		try!(write!(w, "RIFF"));

		// RIFF chunk length (size of overall file)
		try!(w.write_u32::<LittleEndian>(file_len));

		// WAVE chunk start
		try!(write!(w, "WAVE"));

		// Format chunk start
		try!(write!(w, "fmt "));

		// Format chunk length
		try!(w.write_u32::<LittleEndian>(16));

		// Type of format (PCM)
		try!(w.write_u16::<LittleEndian>(1));

		// Number of channels
		try!(w.write_u16::<LittleEndian>(1));

		// Sample rate
		try!(w.write_u32::<LittleEndian>(self.sample_rate));

		// Sample rate * bits per sample * channels / 8
		try!(w.write_u32::<LittleEndian>(self.sample_rate));

		// Bits per sample * channels
		try!(w.write_u16::<LittleEndian>(8));

		// Bits per sample
		try!(w.write_u16::<LittleEndian>(8));

		// Data chunk start
		try!(write!(w, "data"));

		// Data chunk length
		try!(w.write_u32::<LittleEndian>(data_len));

		Ok(())
	}

	fn write_byte(&mut self, byte: u8) -> Result<usize> {
		let mut nbytes = 0;
		nbytes += try!(self.write_pulse(LONG_PULSE));
		let mut bits = byte;
		for _ in 0..8 {
			if bits & 0x01 > 0 {
				nbytes += try!(self.write_pulse(SHORT_PULSE));
				nbytes += try!(self.write_pulse(SHORT_PULSE));
			} else {
				nbytes += try!(self.write_pulse(LONG_PULSE));
			}
			bits = bits >> 1;
		}
		for _ in 0..4 {
			nbytes += try!(self.write_pulse(SHORT_PULSE));
		}
		Ok(nbytes)
	}

	fn write_pulse(&mut self, freq: u32) -> Result<usize> {
		let len = self.sample_rate / (self.bauds * (freq / 1200));
		let scale = 2.0 * f32::consts::PI  / len as f32;
		let func = |x: f32| (f32::sin(scale * x) * 127.0) as i8 as u8 ^ 0x80;
		let bytes = Vec::from_iter((0..len).map(|x| func(x as f32)));
		self.buffer.write(&bytes[..]).map_err(Error::from)
	}
}

#[cfg(test)]
mod test {

	use byteorder::{ByteOrder, LittleEndian};

	use super::*;

	#[test]
	fn should_export_empty_data() {
		let exporter = Exporter::new();
		let mut output: Vec<u8> = Vec::new();
		exporter.export(&mut output).ok();
		assert_eq!("RIFF".as_bytes(), &output[0..4]);
		assert_eq!(44, LittleEndian::read_u32(&output[4..8]));
		assert_eq!("WAVE".as_bytes(), &output[8..12]);
		assert_eq!("fmt ".as_bytes(), &output[12..16]);
		assert_eq!(16, LittleEndian::read_u32(&output[16..20]));
		assert_eq!(1, LittleEndian::read_u16(&output[20..22]));
		assert_eq!(1, LittleEndian::read_u16(&output[22..24]));
		assert_eq!(43200, LittleEndian::read_u32(&output[24..28]));
		assert_eq!(43200, LittleEndian::read_u32(&output[28..32]));
		assert_eq!(8, LittleEndian::read_u16(&output[32..34]));
		assert_eq!(8, LittleEndian::read_u16(&output[34..36]));
		assert_eq!("data".as_bytes(), &output[36..40]);
		assert_eq!(0, LittleEndian::read_u32(&output[40..44]));
	}
}
<commit_msg>Remove custom `Result` type in `wav` module<commit_after>//
// MSX CAS Packager
// Copyright (c) 2015 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::f32;
use std::io;
use std::io::Write;
use std::iter::FromIterator;

use byteorder::{LittleEndian, WriteBytesExt};

const SHORT_PULSE: u32 = 2400;
const LONG_PULSE: u32 = 1200;

const SHORT_HEADER: u32 = 4000;
const LONG_HEADER: u32 = 16000;

/// An object capable to export binary data in WAV format
///
/// The exporter object works by encoding silences, headers and data into
/// an internal buffer. When all the necessary data is encoded, you may use
/// the `export()` method to generate the corresponding WAV header and dump
/// the content into a valid WAV file.
pub struct Exporter {
	bauds: u32,
	sample_rate: u32,
	buffer: Vec<u8>,
}

impl Exporter {

	/// Create a new exporter using default settings
	///
	/// Default settins are 1200 bauds and 43200 samples per second.
	pub fn new() -> Exporter {
		Exporter {
			bauds: 1200,
			sample_rate: 43200,
			buffer: Vec::new(),
		}
	}

	/// Export the encoded data to the given `Write` instance
	///
	/// This method dumps the encoded data into the given `Write` instance. Before
	/// calling this method, you must use the `write_X()` functions to encode
	/// some data.
	pub fn export<W: Write>(&self, w: &mut W) -> io::Result<()> {
		try!(self.write_wave(w));
		try!(w.write(&*self.buffer));
		Ok(())
	}

	/// Write a short header to the internal buffer
	pub fn write_short_header(&mut self) -> io::Result<usize> {
		self.write_header(SHORT_HEADER)
	}

	/// Write a long header to the internal buffer
	pub fn write_long_header(&mut self) -> io::Result<usize> {
		self.write_header(LONG_HEADER)
	}

	/// Write a header comprised by the given amount of pulses to the internal buffer
	pub fn write_header(&mut self, pulses: u32) -> io::Result<usize> {
		let to = pulses * self.bauds / 1200;
		let mut nbytes = 0;
		for _ in 0..to {
			nbytes += try!(self.write_pulse(SHORT_PULSE));
		}
		Ok(nbytes)
	}

	/// Write a short silence (1 second) to the internal buffer
	pub fn write_short_silence(&mut self) -> io::Result<usize> {
		let pulses = self.sample_rate;
		self.write_silence(pulses)
	}

	/// Write a long silence (2 seconds) to the internal buffer
	pub fn write_long_silence(&mut self) -> io::Result<usize> {
		let pulses = self.sample_rate * 2;
		self.write_silence(pulses)
	}

	/// Write a silence comprised by the given amount of pulses to the internal buffer
	pub fn write_silence(&mut self, pulses: u32) ->  io::Result<usize> {
		let mut nbytes = 0;
		for _ in 0..pulses {
			nbytes += try!(self.buffer.write(&[0x80]));
		}
		Ok(nbytes)
	}

	/// Write binary data to the internal buffer
	pub fn write_data(&mut self, data: &[u8]) -> io::Result<usize> {
		let mut nbytes = 0;
		for byte in data {
			nbytes += try!(self.write_byte(*byte));
		}
		Ok(nbytes)
	}

	fn write_wave<W: Write>(&self, w: &mut W) -> io::Result<()> {
		let data_len = self.buffer.len() as u32;
		let file_len = data_len + 44;

		// RIFF chunk start
		try!(write!(w, "RIFF"));

		// RIFF chunk length (size of overall file)
		try!(w.write_u32::<LittleEndian>(file_len));

		// WAVE chunk start
		try!(write!(w, "WAVE"));

		// Format chunk start
		try!(write!(w, "fmt "));

		// Format chunk length
		try!(w.write_u32::<LittleEndian>(16));

		// Type of format (PCM)
		try!(w.write_u16::<LittleEndian>(1));

		// Number of channels
		try!(w.write_u16::<LittleEndian>(1));

		// Sample rate
		try!(w.write_u32::<LittleEndian>(self.sample_rate));

		// Sample rate * bits per sample * channels / 8
		try!(w.write_u32::<LittleEndian>(self.sample_rate));

		// Bits per sample * channels
		try!(w.write_u16::<LittleEndian>(8));

		// Bits per sample
		try!(w.write_u16::<LittleEndian>(8));

		// Data chunk start
		try!(write!(w, "data"));

		// Data chunk length
		try!(w.write_u32::<LittleEndian>(data_len));

		Ok(())
	}

	fn write_byte(&mut self, byte: u8) -> io::Result<usize> {
		let mut nbytes = 0;
		nbytes += try!(self.write_pulse(LONG_PULSE));
		let mut bits = byte;
		for _ in 0..8 {
			if bits & 0x01 > 0 {
				nbytes += try!(self.write_pulse(SHORT_PULSE));
				nbytes += try!(self.write_pulse(SHORT_PULSE));
			} else {
				nbytes += try!(self.write_pulse(LONG_PULSE));
			}
			bits = bits >> 1;
		}
		for _ in 0..4 {
			nbytes += try!(self.write_pulse(SHORT_PULSE));
		}
		Ok(nbytes)
	}

	fn write_pulse(&mut self, freq: u32) -> io::Result<usize> {
		let len = self.sample_rate / (self.bauds * (freq / 1200));
		let scale = 2.0 * f32::consts::PI  / len as f32;
		let func = |x: f32| (f32::sin(scale * x) * 127.0) as i8 as u8 ^ 0x80;
		let bytes = Vec::from_iter((0..len).map(|x| func(x as f32)));
		self.buffer.write(&bytes[..])
	}
}

#[cfg(test)]
mod test {

	use byteorder::{ByteOrder, LittleEndian};

	use super::*;

	#[test]
	fn should_export_empty_data() {
		let exporter = Exporter::new();
		let mut output: Vec<u8> = Vec::new();
		exporter.export(&mut output).ok();
		assert_eq!("RIFF".as_bytes(), &output[0..4]);
		assert_eq!(44, LittleEndian::read_u32(&output[4..8]));
		assert_eq!("WAVE".as_bytes(), &output[8..12]);
		assert_eq!("fmt ".as_bytes(), &output[12..16]);
		assert_eq!(16, LittleEndian::read_u32(&output[16..20]));
		assert_eq!(1, LittleEndian::read_u16(&output[20..22]));
		assert_eq!(1, LittleEndian::read_u16(&output[22..24]));
		assert_eq!(43200, LittleEndian::read_u32(&output[24..28]));
		assert_eq!(43200, LittleEndian::read_u32(&output[28..32]));
		assert_eq!(8, LittleEndian::read_u16(&output[32..34]));
		assert_eq!(8, LittleEndian::read_u16(&output[34..36]));
		assert_eq!("data".as_bytes(), &output[36..40]);
		assert_eq!(0, LittleEndian::read_u32(&output[40..44]));
	}
}
<|endoftext|>


<commit_before>pub mod anilist;
pub mod offline;

use crate::err::Result;
use serde_derive::{Deserialize, Serialize};
use std::borrow::Cow;
use std::fmt;

pub trait RemoteService {
    fn search_info_by_name(&self, name: &str) -> Result<Vec<SeriesInfo>>;
    fn search_info_by_id(&self, id: u32) -> Result<SeriesInfo>;

    fn get_list_entry(&self, id: u32) -> Result<Option<SeriesEntry>>;
    fn update_list_entry(&self, entry: &SeriesEntry) -> Result<()>;

    fn is_offline(&self) -> bool {
        false
    }

    fn parse_score(&self, score: &str) -> Option<u8> {
        score.parse().ok()
    }

    fn score_to_str(&self, score: u8) -> Cow<str> {
        Cow::Owned(score.to_string())
    }
}

pub type Minutes = u32;

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SeriesInfo {
    pub id: u32,
    pub title: SeriesTitle,
    pub episodes: u32,
    pub episode_length: Minutes,
    pub sequel: Option<u32>,
}

impl<'a> Into<Cow<'a, SeriesInfo>> for SeriesInfo {
    fn into(self) -> Cow<'a, SeriesInfo> {
        Cow::Owned(self)
    }
}

impl<'a> Into<Cow<'a, SeriesInfo>> for &'a SeriesInfo {
    fn into(self) -> Cow<'a, SeriesInfo> {
        Cow::Borrowed(self)
    }
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SeriesTitle {
    pub romaji: String,
    pub preferred: String,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct SeriesEntry {
    pub id: u32,
    pub watched_eps: u32,
    pub score: Option<u8>,
    pub status: Status,
    pub times_rewatched: u32,
    pub start_date: Option<chrono::NaiveDate>,
    pub end_date: Option<chrono::NaiveDate>,
}

impl SeriesEntry {
    pub fn new(id: u32) -> SeriesEntry {
        SeriesEntry {
            id,
            watched_eps: 0,
            score: None,
            status: Status::default(),
            times_rewatched: 0,
            start_date: None,
            end_date: None,
        }
    }
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum Status {
    Watching,
    Completed,
    OnHold,
    Dropped,
    PlanToWatch,
    Rewatching,
}

impl Default for Status {
    fn default() -> Status {
        Status::PlanToWatch
    }
}

impl fmt::Display for Status {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let value = match self {
            Status::Watching => "Watching",
            Status::Completed => "Completed",
            Status::OnHold => "On Hold",
            Status::Dropped => "Dropped",
            Status::PlanToWatch => "Plan To Watch",
            Status::Rewatching => "Rewatching",
        };

        write!(f, "{}", value)
    }
}
<commit_msg>[anime] Only return score in default implementation if it's <= 100<commit_after>pub mod anilist;
pub mod offline;

use crate::err::Result;
use serde_derive::{Deserialize, Serialize};
use std::borrow::Cow;
use std::fmt;

pub trait RemoteService {
    fn search_info_by_name(&self, name: &str) -> Result<Vec<SeriesInfo>>;
    fn search_info_by_id(&self, id: u32) -> Result<SeriesInfo>;

    fn get_list_entry(&self, id: u32) -> Result<Option<SeriesEntry>>;
    fn update_list_entry(&self, entry: &SeriesEntry) -> Result<()>;

    fn is_offline(&self) -> bool {
        false
    }

    fn parse_score(&self, score: &str) -> Option<u8> {
        score
            .parse()
            .ok()
            .and_then(|score| if score <= 100 { Some(score) } else { None })
    }

    fn score_to_str(&self, score: u8) -> Cow<str> {
        Cow::Owned(score.to_string())
    }
}

pub type Minutes = u32;

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SeriesInfo {
    pub id: u32,
    pub title: SeriesTitle,
    pub episodes: u32,
    pub episode_length: Minutes,
    pub sequel: Option<u32>,
}

impl<'a> Into<Cow<'a, SeriesInfo>> for SeriesInfo {
    fn into(self) -> Cow<'a, SeriesInfo> {
        Cow::Owned(self)
    }
}

impl<'a> Into<Cow<'a, SeriesInfo>> for &'a SeriesInfo {
    fn into(self) -> Cow<'a, SeriesInfo> {
        Cow::Borrowed(self)
    }
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SeriesTitle {
    pub romaji: String,
    pub preferred: String,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct SeriesEntry {
    pub id: u32,
    pub watched_eps: u32,
    pub score: Option<u8>,
    pub status: Status,
    pub times_rewatched: u32,
    pub start_date: Option<chrono::NaiveDate>,
    pub end_date: Option<chrono::NaiveDate>,
}

impl SeriesEntry {
    pub fn new(id: u32) -> SeriesEntry {
        SeriesEntry {
            id,
            watched_eps: 0,
            score: None,
            status: Status::default(),
            times_rewatched: 0,
            start_date: None,
            end_date: None,
        }
    }
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum Status {
    Watching,
    Completed,
    OnHold,
    Dropped,
    PlanToWatch,
    Rewatching,
}

impl Default for Status {
    fn default() -> Status {
        Status::PlanToWatch
    }
}

impl fmt::Display for Status {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let value = match self {
            Status::Watching => "Watching",
            Status::Completed => "Completed",
            Status::OnHold => "On Hold",
            Status::Dropped => "Dropped",
            Status::PlanToWatch => "Plan To Watch",
            Status::Rewatching => "Rewatching",
        };

        write!(f, "{}", value)
    }
}
<|endoftext|>


<commit_before>
use std::fmt::Debug;

use itertools::zip;

use {Ix, Ix0, Ix1, Ix2, Ix3, Ix4, Ix5, IxDyn, Dim, Dimension, IntoDimension};
use {zipsl, ZipExt};
use super::{stride_offset};
use super::DimPrivate;

/// Tuple or fixed size arrays that can be used to index an array.
///
/// ```
/// use ndarray::arr2;
///
/// let mut a = arr2(&[[0, 1],
///                    [2, 3]]);
/// assert_eq!(a[[0, 1]], 1);
/// assert_eq!(a[[1, 1]], 3);
/// a[[1, 1]] += 1;
/// assert_eq!(a[(1, 1)], 4);
/// ```
///
/// **Note** that `NdIndex` is implemented for all `D where D: Dimension`.
pub unsafe trait NdIndex<E> : Debug {
    #[doc(hidden)]
    fn index_checked(&self, dim: &E, strides: &E) -> Option<isize>;
    fn index_unchecked(&self, strides: &E) -> isize;
}

unsafe impl<D> NdIndex<D> for D
    where D: Dimension
{
    fn index_checked(&self, dim: &D, strides: &D) -> Option<isize> {
        dim.stride_offset_checked(strides, self)
    }
    fn index_unchecked(&self, strides: &D) -> isize {
        D::stride_offset(self, strides)
    }
}

unsafe impl NdIndex<Ix0> for () {
    #[inline]
    fn index_checked(&self, dim: &Ix0, strides: &Ix0) -> Option<isize> {
        dim.stride_offset_checked(strides, &Ix0())
    }
    #[inline(always)]
    fn index_unchecked(&self, _strides: &Ix0) -> isize {
        0
    }
}

unsafe impl NdIndex<Ix1> for Ix {
    #[inline]
    fn index_checked(&self, dim: &Ix1, strides: &Ix1) -> Option<isize> {
        dim.stride_offset_checked(strides, &Ix1(*self))
    }
    #[inline(always)]
    fn index_unchecked(&self, strides: &Ix1) -> isize {
        stride_offset(*self, get!(strides, 0))
    }
}

unsafe impl NdIndex<Ix2> for (Ix, Ix) {
    #[inline]
    fn index_checked(&self, dim: &Ix2, strides: &Ix2) -> Option<isize> {
        dim.stride_offset_checked(strides, &Ix2(self.0, self.1))
    }
    #[inline]
    fn index_unchecked(&self, strides: &Ix2) -> isize {
        stride_offset(self.0, get!(strides, 0)) +
        stride_offset(self.1, get!(strides, 1))
    }
}
unsafe impl NdIndex<Ix3> for (Ix, Ix, Ix) {
    #[inline]
    fn index_checked(&self, dim: &Ix3, strides: &Ix3) -> Option<isize> {
        dim.stride_offset_checked(strides, &self.into_dimension())
    }

    #[inline]
    fn index_unchecked(&self, strides: &Ix3) -> isize {
        stride_offset(self.0, get!(strides, 0)) +
        stride_offset(self.1, get!(strides, 1)) +
        stride_offset(self.2, get!(strides, 2))
    }
}

unsafe impl NdIndex<Ix4> for (Ix, Ix, Ix, Ix) {
    #[inline]
    fn index_checked(&self, dim: &Ix4, strides: &Ix4) -> Option<isize> {
        dim.stride_offset_checked(strides, &self.into_dimension())
    }
    #[inline]
    fn index_unchecked(&self, strides: &Ix4) -> isize {
        zip(strides.ix(), self.into_dimension().ix()).map(|(&s, &i)| stride_offset(i, s)).sum()
    }
}
unsafe impl NdIndex<Ix5> for (Ix, Ix, Ix, Ix, Ix) {
    #[inline]
    fn index_checked(&self, dim: &Ix5, strides: &Ix5) -> Option<isize> {
        dim.stride_offset_checked(strides, &self.into_dimension())
    }
    #[inline]
    fn index_unchecked(&self, strides: &Ix5) -> isize {
        zip(strides.ix(), self.into_dimension().ix()).map(|(&s, &i)| stride_offset(i, s)).sum()
    }
}

unsafe impl NdIndex<Ix2> for [Ix; 2] {
    #[inline]
    fn index_checked(&self, dim: &Ix2, strides: &Ix2) -> Option<isize> {
        dim.stride_offset_checked(strides, &Ix2(self[0], self[1]))
    }
    #[inline]
    fn index_unchecked(&self, strides: &Ix2) -> isize {
        stride_offset(self[0], get!(strides, 0)) +
        stride_offset(self[1], get!(strides, 1))
    }
}

unsafe impl NdIndex<Ix3> for [Ix; 3] {
    #[inline]
    fn index_checked(&self, dim: &Ix3, strides: &Ix3) -> Option<isize> {
        dim.stride_offset_checked(strides, &Ix3(self[0], self[1], self[2]))
    }
    #[inline]
    fn index_unchecked(&self, strides: &Ix3) -> isize {
        stride_offset(self[0], get!(strides, 0)) +
        stride_offset(self[1], get!(strides, 1)) +
        stride_offset(self[2], get!(strides, 2))
    }
}

impl<'a> IntoDimension for &'a [Ix] {
    type Dim = Dim<Vec<Ix>>;
    fn into_dimension(self) -> Self::Dim {
        Dim(self.to_vec())
    }
}

unsafe impl<'a> NdIndex<IxDyn> for &'a [Ix] {
    fn index_checked(&self, dim: &IxDyn, strides: &IxDyn) -> Option<isize> {
        let mut offset = 0;
        for (&d, &i, &s) in zipsl(&dim[..], &self[..]).zip_cons(strides.slice()) {
            if i >= d {
                return None;
            }
            offset += stride_offset(i, s);
        }
        Some(offset)
    }
    fn index_unchecked(&self, strides: &IxDyn) -> isize {
        zip(strides.ix(), *self).map(|(&s, &i)| stride_offset(i, s)).sum()
    }
}

unsafe impl NdIndex<IxDyn> for Vec<Ix> {
    fn index_checked(&self, dim: &IxDyn, strides: &IxDyn) -> Option<isize> {
        let mut offset = 0;
        for (&d, &i, &s) in zipsl(&dim[..], &self[..]).zip_cons(strides.slice()) {
            if i >= d {
                return None;
            }
            offset += stride_offset(i, s);
        }
        Some(offset)
    }
    fn index_unchecked(&self, strides: &IxDyn) -> isize {
        zip(strides.ix(), self).map(|(&s, &i)| stride_offset(i, s)).sum()
    }
}
<commit_msg>Add missing NdIndex impls<commit_after>
use std::fmt::Debug;

use itertools::zip;

use {Ix, Ix0, Ix1, Ix2, Ix3, Ix4, Ix5, IxDyn, Dim, Dimension, IntoDimension};
use {zipsl, ZipExt};
use super::{stride_offset};
use super::DimPrivate;

/// Tuple or fixed size arrays that can be used to index an array.
///
/// ```
/// use ndarray::arr2;
///
/// let mut a = arr2(&[[0, 1],
///                    [2, 3]]);
/// assert_eq!(a[[0, 1]], 1);
/// assert_eq!(a[[1, 1]], 3);
/// a[[1, 1]] += 1;
/// assert_eq!(a[(1, 1)], 4);
/// ```
///
/// **Note** that `NdIndex` is implemented for all `D where D: Dimension`.
pub unsafe trait NdIndex<E> : Debug {
    #[doc(hidden)]
    fn index_checked(&self, dim: &E, strides: &E) -> Option<isize>;
    fn index_unchecked(&self, strides: &E) -> isize;
}

unsafe impl<D> NdIndex<D> for D
    where D: Dimension
{
    fn index_checked(&self, dim: &D, strides: &D) -> Option<isize> {
        dim.stride_offset_checked(strides, self)
    }
    fn index_unchecked(&self, strides: &D) -> isize {
        D::stride_offset(self, strides)
    }
}

unsafe impl NdIndex<Ix0> for () {
    #[inline]
    fn index_checked(&self, dim: &Ix0, strides: &Ix0) -> Option<isize> {
        dim.stride_offset_checked(strides, &Ix0())
    }
    #[inline(always)]
    fn index_unchecked(&self, _strides: &Ix0) -> isize {
        0
    }
}

unsafe impl NdIndex<Ix1> for Ix {
    #[inline]
    fn index_checked(&self, dim: &Ix1, strides: &Ix1) -> Option<isize> {
        dim.stride_offset_checked(strides, &Ix1(*self))
    }
    #[inline(always)]
    fn index_unchecked(&self, strides: &Ix1) -> isize {
        stride_offset(*self, get!(strides, 0))
    }
}

unsafe impl NdIndex<Ix2> for (Ix, Ix) {
    #[inline]
    fn index_checked(&self, dim: &Ix2, strides: &Ix2) -> Option<isize> {
        dim.stride_offset_checked(strides, &Ix2(self.0, self.1))
    }
    #[inline]
    fn index_unchecked(&self, strides: &Ix2) -> isize {
        stride_offset(self.0, get!(strides, 0)) +
        stride_offset(self.1, get!(strides, 1))
    }
}
unsafe impl NdIndex<Ix3> for (Ix, Ix, Ix) {
    #[inline]
    fn index_checked(&self, dim: &Ix3, strides: &Ix3) -> Option<isize> {
        dim.stride_offset_checked(strides, &self.into_dimension())
    }

    #[inline]
    fn index_unchecked(&self, strides: &Ix3) -> isize {
        stride_offset(self.0, get!(strides, 0)) +
        stride_offset(self.1, get!(strides, 1)) +
        stride_offset(self.2, get!(strides, 2))
    }
}

unsafe impl NdIndex<Ix4> for (Ix, Ix, Ix, Ix) {
    #[inline]
    fn index_checked(&self, dim: &Ix4, strides: &Ix4) -> Option<isize> {
        dim.stride_offset_checked(strides, &self.into_dimension())
    }
    #[inline]
    fn index_unchecked(&self, strides: &Ix4) -> isize {
        zip(strides.ix(), self.into_dimension().ix()).map(|(&s, &i)| stride_offset(i, s)).sum()
    }
}
unsafe impl NdIndex<Ix5> for (Ix, Ix, Ix, Ix, Ix) {
    #[inline]
    fn index_checked(&self, dim: &Ix5, strides: &Ix5) -> Option<isize> {
        dim.stride_offset_checked(strides, &self.into_dimension())
    }
    #[inline]
    fn index_unchecked(&self, strides: &Ix5) -> isize {
        zip(strides.ix(), self.into_dimension().ix()).map(|(&s, &i)| stride_offset(i, s)).sum()
    }
}

unsafe impl NdIndex<Ix2> for [Ix; 2] {
    #[inline]
    fn index_checked(&self, dim: &Ix2, strides: &Ix2) -> Option<isize> {
        dim.stride_offset_checked(strides, &Ix2(self[0], self[1]))
    }
    #[inline]
    fn index_unchecked(&self, strides: &Ix2) -> isize {
        stride_offset(self[0], get!(strides, 0)) +
        stride_offset(self[1], get!(strides, 1))
    }
}

unsafe impl NdIndex<Ix3> for [Ix; 3] {
    #[inline]
    fn index_checked(&self, dim: &Ix3, strides: &Ix3) -> Option<isize> {
        dim.stride_offset_checked(strides, &Ix3(self[0], self[1], self[2]))
    }
    #[inline]
    fn index_unchecked(&self, strides: &Ix3) -> isize {
        stride_offset(self[0], get!(strides, 0)) +
        stride_offset(self[1], get!(strides, 1)) +
        stride_offset(self[2], get!(strides, 2))
    }
}

unsafe impl NdIndex<Ix4> for [Ix; 4] {
    #[inline]
    fn index_checked(&self, dim: &Ix4, strides: &Ix4) -> Option<isize> {
        dim.stride_offset_checked(strides, &self.into_dimension())
    }
    #[inline]
    fn index_unchecked(&self, strides: &Ix4) -> isize {
        stride_offset(self[0], get!(strides, 0)) +
        stride_offset(self[1], get!(strides, 1)) +
        stride_offset(self[2], get!(strides, 2)) +
        stride_offset(self[3], get!(strides, 3)) +
        0
    }
}

unsafe impl NdIndex<Ix5> for [Ix; 5] {
    #[inline]
    fn index_checked(&self, dim: &Ix5, strides: &Ix5) -> Option<isize> {
        dim.stride_offset_checked(strides, &self.into_dimension())
    }
    #[inline]
    fn index_unchecked(&self, strides: &Ix5) -> isize {
        stride_offset(self[0], get!(strides, 0)) +
        stride_offset(self[1], get!(strides, 1)) +
        stride_offset(self[2], get!(strides, 2)) +
        stride_offset(self[3], get!(strides, 3)) +
        stride_offset(self[4], get!(strides, 4)) +
        0
    }
}

impl<'a> IntoDimension for &'a [Ix] {
    type Dim = Dim<Vec<Ix>>;
    fn into_dimension(self) -> Self::Dim {
        Dim(self.to_vec())
    }
}

unsafe impl<'a> NdIndex<IxDyn> for &'a [Ix] {
    fn index_checked(&self, dim: &IxDyn, strides: &IxDyn) -> Option<isize> {
        let mut offset = 0;
        for (&d, &i, &s) in zipsl(&dim[..], &self[..]).zip_cons(strides.slice()) {
            if i >= d {
                return None;
            }
            offset += stride_offset(i, s);
        }
        Some(offset)
    }
    fn index_unchecked(&self, strides: &IxDyn) -> isize {
        zip(strides.ix(), *self).map(|(&s, &i)| stride_offset(i, s)).sum()
    }
}

unsafe impl NdIndex<IxDyn> for Vec<Ix> {
    fn index_checked(&self, dim: &IxDyn, strides: &IxDyn) -> Option<isize> {
        let mut offset = 0;
        for (&d, &i, &s) in zipsl(&dim[..], &self[..]).zip_cons(strides.slice()) {
            if i >= d {
                return None;
            }
            offset += stride_offset(i, s);
        }
        Some(offset)
    }
    fn index_unchecked(&self, strides: &IxDyn) -> isize {
        zip(strides.ix(), self).map(|(&s, &i)| stride_offset(i, s)).sum()
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use stb_image::bindgen::*;

use std::libc;
use std::libc::{c_void, c_int};
use std::ptr::{is_null, to_mut_unsafe_ptr};
use std::task;
use std::vec::raw::from_buf_raw;

pub struct Image<T> {
    width   : uint,
    height  : uint,
    depth   : uint,
    data    : ~[T],
}

pub fn new_image<T>(width: uint, height: uint, depth: uint, data: ~[T]) -> Image<T> {
    Image::<T> {
        width   : width,
        height  : height,
        depth   : depth,
        data    : data,
    }
}

enum LoadResult {
    Error,
    ImageU8(Image<u8>),
    ImageF32(Image<f32>),
}

pub fn load(path: ~str) -> LoadResult {
    let force_depth = 0;
    load_with_depth(path, force_depth, false)
}

#[fixed_stack_segment] #[inline(never)]
fn load_internal<T>(buf : *T, w : c_int, h : c_int, d : c_int) -> Image<T> {
    unsafe {
        // FIXME: Shouldn't copy; instead we should use a sendable resource. They
        // aren't particularly safe yet though.
        let data = from_buf_raw(buf, (w * h * d) as uint);
        libc::free(buf as *c_void);
        Image::<T>{
            width   : w as uint,
            height  : h as uint,
            depth   : d as uint,
            data    : data}
    }
}

#[fixed_stack_segment] #[inline(never)]
pub fn load_with_depth(path: ~str, force_depth: uint, convert_hdr:bool) -> LoadResult {
    unsafe {
        do task::unkillable {
            let mut width   = 0 as c_int;
            let mut height  = 0 as c_int;
            let mut depth   = 0 as c_int;
            do path.to_c_str().with_ref |bytes| {
                if !convert_hdr && stbi_is_hdr(bytes)!=0   {
                    let buffer = stbi_loadf(bytes,
                                            to_mut_unsafe_ptr(&mut width),
                                            to_mut_unsafe_ptr(&mut height),
                                            to_mut_unsafe_ptr(&mut depth),
                                            force_depth as c_int);
                    if is_null(buffer) {
                        Error
                    } else {
                        ImageF32( load_internal(buffer,width,height,depth) )
                    }
                } else {
                    let buffer = stbi_load(bytes,
                                           to_mut_unsafe_ptr(&mut width),
                                           to_mut_unsafe_ptr(&mut height),
                                           to_mut_unsafe_ptr(&mut depth),
                                           force_depth as c_int);
                    if is_null(buffer) {
                        Error
                    } else {
                        ImageU8( load_internal(buffer,width,height,depth) )
                    }
                }
            }
        }
    }
}

#[fixed_stack_segment] #[inline(never)]
pub fn load_from_memory(buffer: &[u8]) -> LoadResult {
    let force_depth = 0;
    load_from_memory_with_depth(buffer, force_depth, false)
}

#[fixed_stack_segment] #[inline(never)]
pub fn load_from_memory_with_depth(buffer: &[u8], force_depth: uint, convert_hdr:bool) -> LoadResult {
    unsafe {
        do task::unkillable {
            let mut width = 0 as c_int;
            let mut height = 0 as c_int;
            let mut depth = 0 as c_int;
            do buffer.as_imm_buf |bytes, len| {
                if !convert_hdr && stbi_is_hdr_from_memory(bytes, len as c_int) != 0 {
                    let buffer = stbi_loadf_from_memory(bytes,
                                                        len as c_int,
                                                        to_mut_unsafe_ptr(&mut width),
                                                        to_mut_unsafe_ptr(&mut height),
                                                        to_mut_unsafe_ptr(&mut depth),
                                                        force_depth as c_int);
                    if is_null(buffer) {
                        Error
                    } else {
                        let actual_depth = if force_depth != 0 { force_depth as c_int } else { depth };
                        ImageF32( load_internal(buffer,width,height,actual_depth) )
                    }
                } else {
                    let buffer = stbi_load_from_memory(bytes,
                                                       len as c_int,
                                                       to_mut_unsafe_ptr(&mut width),
                                                       to_mut_unsafe_ptr(&mut height),
                                                       to_mut_unsafe_ptr(&mut depth),
                                                       force_depth as c_int);
                    if is_null(buffer) {
                        Error
                    } else {
                        let actual_depth = if force_depth != 0 { force_depth as c_int } else { depth };
                        ImageU8( load_internal(buffer,width,height,actual_depth) )
                    }
                }
            }
        }
    }
}
<commit_msg>Exposed LoadResult to public<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use stb_image::bindgen::*;

use std::libc;
use std::libc::{c_void, c_int};
use std::ptr::{is_null, to_mut_unsafe_ptr};
use std::task;
use std::vec::raw::from_buf_raw;

pub struct Image<T> {
    width   : uint,
    height  : uint,
    depth   : uint,
    data    : ~[T],
}

pub fn new_image<T>(width: uint, height: uint, depth: uint, data: ~[T]) -> Image<T> {
    Image::<T> {
        width   : width,
        height  : height,
        depth   : depth,
        data    : data,
    }
}

pub enum LoadResult {
    Error,
    ImageU8(Image<u8>),
    ImageF32(Image<f32>),
}

pub fn load(path: ~str) -> LoadResult {
    let force_depth = 0;
    load_with_depth(path, force_depth, false)
}

#[fixed_stack_segment] #[inline(never)]
fn load_internal<T>(buf : *T, w : c_int, h : c_int, d : c_int) -> Image<T> {
    unsafe {
        // FIXME: Shouldn't copy; instead we should use a sendable resource. They
        // aren't particularly safe yet though.
        let data = from_buf_raw(buf, (w * h * d) as uint);
        libc::free(buf as *c_void);
        Image::<T>{
            width   : w as uint,
            height  : h as uint,
            depth   : d as uint,
            data    : data}
    }
}

#[fixed_stack_segment] #[inline(never)]
pub fn load_with_depth(path: ~str, force_depth: uint, convert_hdr:bool) -> LoadResult {
    unsafe {
        do task::unkillable {
            let mut width   = 0 as c_int;
            let mut height  = 0 as c_int;
            let mut depth   = 0 as c_int;
            do path.to_c_str().with_ref |bytes| {
                if !convert_hdr && stbi_is_hdr(bytes)!=0   {
                    let buffer = stbi_loadf(bytes,
                                            to_mut_unsafe_ptr(&mut width),
                                            to_mut_unsafe_ptr(&mut height),
                                            to_mut_unsafe_ptr(&mut depth),
                                            force_depth as c_int);
                    if is_null(buffer) {
                        Error
                    } else {
                        ImageF32( load_internal(buffer,width,height,depth) )
                    }
                } else {
                    let buffer = stbi_load(bytes,
                                           to_mut_unsafe_ptr(&mut width),
                                           to_mut_unsafe_ptr(&mut height),
                                           to_mut_unsafe_ptr(&mut depth),
                                           force_depth as c_int);
                    if is_null(buffer) {
                        Error
                    } else {
                        ImageU8( load_internal(buffer,width,height,depth) )
                    }
                }
            }
        }
    }
}

#[fixed_stack_segment] #[inline(never)]
pub fn load_from_memory(buffer: &[u8]) -> LoadResult {
    let force_depth = 0;
    load_from_memory_with_depth(buffer, force_depth, false)
}

#[fixed_stack_segment] #[inline(never)]
pub fn load_from_memory_with_depth(buffer: &[u8], force_depth: uint, convert_hdr:bool) -> LoadResult {
    unsafe {
        do task::unkillable {
            let mut width = 0 as c_int;
            let mut height = 0 as c_int;
            let mut depth = 0 as c_int;
            do buffer.as_imm_buf |bytes, len| {
                if !convert_hdr && stbi_is_hdr_from_memory(bytes, len as c_int) != 0 {
                    let buffer = stbi_loadf_from_memory(bytes,
                                                        len as c_int,
                                                        to_mut_unsafe_ptr(&mut width),
                                                        to_mut_unsafe_ptr(&mut height),
                                                        to_mut_unsafe_ptr(&mut depth),
                                                        force_depth as c_int);
                    if is_null(buffer) {
                        Error
                    } else {
                        let actual_depth = if force_depth != 0 { force_depth as c_int } else { depth };
                        ImageF32( load_internal(buffer,width,height,actual_depth) )
                    }
                } else {
                    let buffer = stbi_load_from_memory(bytes,
                                                       len as c_int,
                                                       to_mut_unsafe_ptr(&mut width),
                                                       to_mut_unsafe_ptr(&mut height),
                                                       to_mut_unsafe_ptr(&mut depth),
                                                       force_depth as c_int);
                    if is_null(buffer) {
                        Error
                    } else {
                        let actual_depth = if force_depth != 0 { force_depth as c_int } else { depth };
                        ImageU8( load_internal(buffer,width,height,actual_depth) )
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Interfaces for building [docker](https://www.docker.com/) containers

extern crate rustc_serialize;
extern crate jed;
extern crate url;

use self::super::{Docker, Result};
use self::super::transport::Body;
use self::super::rep::{ContainerCreateInfo, Event};
use self::super::rep::Container as ContainerRep;
use std::collections::{BTreeMap, HashMap};
use rustc_serialize::json::{self, Json, ToJson};
use url::form_urlencoded;

/// Interface for building container list request
pub struct ContainerListBuilder<'a> {
    docker: &'a Docker,
    params: HashMap<&'static str, String>,
}

impl<'a> ContainerListBuilder<'a> {
    pub fn new(docker: &'a Docker) -> ContainerListBuilder<'a> {
        ContainerListBuilder {
            docker: docker,
            params: HashMap::new(),
        }
    }

    pub fn all(&mut self) -> &mut ContainerListBuilder<'a> {
        self.params.insert("all", "true".to_owned());
        self
    }

    pub fn since(&mut self, since: &str) -> &mut ContainerListBuilder<'a> {
        self.params.insert("since", since.to_owned());
        self
    }

    pub fn before(&mut self, before: &str) -> &mut ContainerListBuilder<'a> {
        self.params.insert("before", before.to_owned());
        self
    }

    pub fn sized(&mut self) -> &mut ContainerListBuilder<'a> {
        self.params.insert("size", "true".to_owned());
        self
    }

    pub fn build(self) -> Result<Vec<ContainerRep>> {
        let mut path = vec!["/containers/json".to_owned()];
        if !self.params.is_empty() {
            let encoded = form_urlencoded::serialize(self.params);
            path.push(encoded)
        }
        let raw = try!(self.docker.get(&path.join("?")));
        Ok(try!(json::decode::<Vec<ContainerRep>>(&raw)))
    }
}

/// Interface for building a new docker container from an existing image
pub struct ContainerBuilder<'a, 'b> {
    docker: &'a Docker,
    image: &'b str,
    hostname: Option<String>,
    user: Option<String>,
    memory: Option<u64>,
}

impl<'a, 'b> ContainerBuilder<'a, 'b> {
    pub fn new(docker: &'a Docker, image: &'b str) -> ContainerBuilder<'a, 'b> {
        ContainerBuilder {
            docker: docker,
            image: image,
            hostname: None,
            user: None,
            memory: None,
        }
    }

    pub fn hostname(&mut self, h: &str) -> &mut ContainerBuilder<'a, 'b> {
        self.hostname = Some(h.to_owned());
        self
    }

    pub fn user(&mut self, u: &str) -> &mut ContainerBuilder<'a, 'b> {
        self.user = Some(u.to_owned());
        self
    }

    pub fn build(&self) -> Result<ContainerCreateInfo> {
        let mut body = BTreeMap::new();
        body.insert("Image".to_owned(), self.image.to_json());
        let json_obj: Json = body.to_json();
        let data = try!(json::encode(&json_obj));
        let mut bytes = data.as_bytes();
        let raw = try!(self.docker.post("/containers/create",
                                        Some(Body::new(&mut Box::new(&mut bytes),
                                                       bytes.len() as u64))));
        Ok(try!(json::decode::<ContainerCreateInfo>(&raw)))
    }
}

/// Interface for buiding an events request
pub struct EventsBuilder<'a, 'b, 'c> {
    docker: &'a Docker,
    since: Option<&'b u64>,
    until: Option<&'c u64>,
}

impl<'a, 'b, 'c> EventsBuilder<'a, 'b, 'c> {
    pub fn new(docker: &'a Docker) -> EventsBuilder<'a, 'b, 'c> {
        EventsBuilder {
            docker: docker,
            since: None,
            until: None,
        }
    }

    /// Filter events since a given timestamp
    pub fn since(&mut self, ts: &'b u64) -> &mut EventsBuilder<'a, 'b, 'c> {
        self.since = Some(ts);
        self
    }

    /// Filter events until a given timestamp
    pub fn until(&mut self, ts: &'c u64) -> &mut EventsBuilder<'a, 'b, 'c> {
        self.until = Some(ts);
        self
    }

    /// Returns an interator over streamed docker events
    pub fn build(&self) -> Result<Box<Iterator<Item = Event>>> {
        let mut params = Vec::new();
        if let Some(s) = self.since {
            params.push(("since", s.to_string()));
        }
        if let Some(u) = self.until {
            params.push(("until", u.to_string()));
        }
        let mut path = vec!["/events".to_owned()];
        if !params.is_empty() {
            let encoded = form_urlencoded::serialize(params);
            path.push(encoded)
        }
        let raw = try!(self.docker.stream_get(&path.join("?")[..]));
        let it = jed::Iter::new(raw).into_iter().map(|j| {
            // fixme: better error handling
            let s = json::encode(&j).unwrap();
            json::decode::<Event>(&s).unwrap()
        });
        Ok(Box::new(it))
    }
}
<commit_msg>can not move out of a borrowed ctx<commit_after>//! Interfaces for building [docker](https://www.docker.com/) containers

extern crate rustc_serialize;
extern crate jed;
extern crate url;

use self::super::{Docker, Result};
use self::super::transport::Body;
use self::super::rep::{ContainerCreateInfo, Event};
use self::super::rep::Container as ContainerRep;
use std::collections::{BTreeMap, HashMap};
use rustc_serialize::json::{self, Json, ToJson};
use url::form_urlencoded;

/// Interface for building container list request
pub struct ContainerListBuilder<'a> {
    docker: &'a Docker,
    params: HashMap<&'static str, String>,
}

impl<'a> ContainerListBuilder<'a> {
    pub fn new(docker: &'a Docker) -> ContainerListBuilder<'a> {
        ContainerListBuilder {
            docker: docker,
            params: HashMap::new(),
        }
    }

    pub fn all(&mut self) -> &mut ContainerListBuilder<'a> {
        self.params.insert("all", "true".to_owned());
        self
    }

    pub fn since(&mut self, since: &str) -> &mut ContainerListBuilder<'a> {
        self.params.insert("since", since.to_owned());
        self
    }

    pub fn before(&mut self, before: &str) -> &mut ContainerListBuilder<'a> {
        self.params.insert("before", before.to_owned());
        self
    }

    pub fn sized(&mut self) -> &mut ContainerListBuilder<'a> {
        self.params.insert("size", "true".to_owned());
        self
    }

    pub fn build(&self) -> Result<Vec<ContainerRep>> {
        let mut path = vec!["/containers/json".to_owned()];
        if !self.params.is_empty() {
            let encoded = form_urlencoded::serialize(&self.params);
            path.push(encoded)
        }
        let raw = try!(self.docker.get(&path.join("?")));
        Ok(try!(json::decode::<Vec<ContainerRep>>(&raw)))
    }
}

/// Interface for building a new docker container from an existing image
pub struct ContainerBuilder<'a, 'b> {
    docker: &'a Docker,
    image: &'b str,
    hostname: Option<String>,
    user: Option<String>,
    memory: Option<u64>,
}

impl<'a, 'b> ContainerBuilder<'a, 'b> {
    pub fn new(docker: &'a Docker, image: &'b str) -> ContainerBuilder<'a, 'b> {
        ContainerBuilder {
            docker: docker,
            image: image,
            hostname: None,
            user: None,
            memory: None,
        }
    }

    pub fn hostname(&mut self, h: &str) -> &mut ContainerBuilder<'a, 'b> {
        self.hostname = Some(h.to_owned());
        self
    }

    pub fn user(&mut self, u: &str) -> &mut ContainerBuilder<'a, 'b> {
        self.user = Some(u.to_owned());
        self
    }

    pub fn build(&self) -> Result<ContainerCreateInfo> {
        let mut body = BTreeMap::new();
        body.insert("Image".to_owned(), self.image.to_json());
        let json_obj: Json = body.to_json();
        let data = try!(json::encode(&json_obj));
        let mut bytes = data.as_bytes();
        let raw = try!(self.docker.post("/containers/create",
                                        Some(Body::new(&mut Box::new(&mut bytes),
                                                       bytes.len() as u64))));
        Ok(try!(json::decode::<ContainerCreateInfo>(&raw)))
    }
}

/// Interface for buiding an events request
pub struct EventsBuilder<'a, 'b, 'c> {
    docker: &'a Docker,
    since: Option<&'b u64>,
    until: Option<&'c u64>,
}

impl<'a, 'b, 'c> EventsBuilder<'a, 'b, 'c> {
    pub fn new(docker: &'a Docker) -> EventsBuilder<'a, 'b, 'c> {
        EventsBuilder {
            docker: docker,
            since: None,
            until: None,
        }
    }

    /// Filter events since a given timestamp
    pub fn since(&mut self, ts: &'b u64) -> &mut EventsBuilder<'a, 'b, 'c> {
        self.since = Some(ts);
        self
    }

    /// Filter events until a given timestamp
    pub fn until(&mut self, ts: &'c u64) -> &mut EventsBuilder<'a, 'b, 'c> {
        self.until = Some(ts);
        self
    }

    /// Returns an interator over streamed docker events
    pub fn build(&self) -> Result<Box<Iterator<Item = Event>>> {
        let mut params = Vec::new();
        if let Some(s) = self.since {
            params.push(("since", s.to_string()));
        }
        if let Some(u) = self.until {
            params.push(("until", u.to_string()));
        }
        let mut path = vec!["/events".to_owned()];
        if !params.is_empty() {
            let encoded = form_urlencoded::serialize(params);
            path.push(encoded)
        }
        let raw = try!(self.docker.stream_get(&path.join("?")[..]));
        let it = jed::Iter::new(raw).into_iter().map(|j| {
            // fixme: better error handling
            let s = json::encode(&j).unwrap();
            json::decode::<Event>(&s).unwrap()
        });
        Ok(Box::new(it))
    }
}
<|endoftext|>


<commit_before>//! HTTP Request handling.
//!
//! # Example
//! ```
//! use cabot::RequestBuilder;
//!
//! let request = RequestBuilder::new("http://localhost/")
//!     .set_http_method("POST")
//!     .add_header("Content-Type: application/json")
//!     .set_body("{}")
//!     .build()
//!     .unwrap();
//!     let attempt = "POST / HTTP/1.1\r\nContent-Type: \
//!                    application/json\r\nHost: localhost\r\nConnection: \
//!                    close\r\nContent-Length: 2\r\n\r\n{}";
//! assert_eq!(request.to_string(), attempt.to_string());
//! ```

use url::{self, Url};

use results::{CabotResult, CabotError};

/// An HTTP Request representation.
///
/// Request is build using [RequestBuilder](../request/struct.RequestBuilder.html)
/// and them consume by the [Client](../client/struct.Client.html)
/// to perform the query.
pub struct Request {
    host: String,
    port: u16,
    authority: String,
    is_domain: bool,
    scheme: String,
    http_method: String,
    request_uri: String,
    http_version: String,
    headers: Vec<String>,
    body: Option<String>,
}

impl Request {
    fn new(host: String,
           port: u16,
           authority: String,
           is_domain: bool,
           scheme: String,
           http_method: String,
           request_uri: String,
           http_version: String,
           headers: Vec<String>,
           body: Option<String>)
           -> Request {
        Request {
            host: host,
            port: port,
            authority: authority,
            is_domain: is_domain,
            scheme: scheme,
            http_method: http_method,
            request_uri: request_uri,
            http_version: http_version,
            headers: headers,
            body: body,
        }
    }

    /// The HTTP verb used to perform the request,
    /// such as GET, POST, ...
    pub fn http_method(&self) -> &str {
        self.http_method.as_str()
    }

    /// The HTTP Body of the request.
    pub fn body(&self) -> Option<&str> {
        match self.body {
            Some(ref payload) => Some(payload.as_str()),
            None => None,
        }
    }

    /// The Version of the HTTP to perform the request.
    pub fn http_version(&self) -> &str {
        self.http_version.as_str()
    }

    /// The server name to connect. can be a name to resolve or an IP address.
    pub fn host(&self) -> &str {
        self.host.as_str()
    }

    /// The TCP server port to connect.
    pub fn port(&self) -> u16 {
        self.port
    }

    /// The authority part of the url (`host`:`port`).
    pub fn authority(&self) -> &str {
        self.authority.as_str()
    }

    /// The protocol scheme, can be http or https.
    pub fn scheme(&self) -> &str {
        self.scheme.as_str()
    }

    /// The URI to send, something like a PATH_INFO and a querystring.
    pub fn request_uri(&self) -> &str {
        self.request_uri.as_str()
    }

    /// The String representation of the query to send to the server.
    pub fn to_string(&self) -> String {
        let mut resp = format!("{} {} {}\r\n",
                               self.http_method(),
                               self.request_uri(),
                               self.http_version());
        if self.headers.len() > 0 {
            resp.push_str(self.headers.as_slice().join("\r\n").as_str());
            resp.push_str("\r\n");
        }
        if self.is_domain {
            resp.push_str(format!("Host: {}\r\n", self.host()).as_str());
        }
        resp.push_str("Connection: close\r\n");
        if let Some(payload) = self.body() {
            resp.push_str(format!("Content-Length: {}\r\n", payload.len()).as_str());
            resp.push_str("\r\n");
            resp.push_str(payload);
        } else {
            resp.push_str("\r\n");
        }
        resp
    }
}

/// Construct [Request](../request/struct.Request.html)
pub struct RequestBuilder {
    http_method: String,
    url: Result<Url, url::ParseError>,
    http_version: String,
    headers: Vec<String>,
    body: Option<String>,
}

impl RequestBuilder {
    /// Create a new RequestBuilder with the given url.
    ///
    /// `url` will be parsed to get the host to contact and the uri to send.
    /// When building a request object after creating the builder,
    /// the http method will be `GET` with neither header nor body and
    /// the http version will be `HTTP/1.1`
    pub fn new(url: &str) -> Self {
        let url = url.parse::<Url>();
        RequestBuilder {
            http_method: "GET".to_owned(),
            url: url,
            http_version: "HTTP/1.1".to_owned(),
            headers: Vec::new(),
            body: None,
        }
    }

    /// Replace the url in case the RequestBuilder is used many time
    /// for multiple query.
    pub fn set_url(mut self, url: &str) -> Self {
        self.url = url.parse::<Url>();
        self
    }

    /// Set the http method such as `GET` `POST`. Default value is `GET`.
    pub fn set_http_method(mut self, http_method: &str) -> Self {
        self.http_method = http_method.to_owned();
        self
    }

    /// Set the protocol version to use.. Default value is `HTTP/1.1`.
    pub fn set_http_version(mut self, http_version: &str) -> Self {
        self.http_version = http_version.to_owned();
        self
    }

    /// Add a HTTP header.
    pub fn add_header(mut self, header: &str) -> Self {
        self.headers.push(header.to_owned());
        self
    }

    /// Add many headers.
    pub fn add_headers(mut self, headers: &[&str]) -> Self {
        for header in headers {
            self.headers.push(header.to_string());
        }
        self
    }

    /// Set a body to send in the query. By default a query has no body.
    pub fn set_body(mut self, body: &str) -> Self {
        self.body = Some(body.to_owned());
        self
    }

    /// Construct the [Request](../request/struct.Request.html).
    /// To perform the query, a [Client](../client/struct.Client.html)
    /// has to be created.
    ///
    /// Errors:
    ///
    ///   - CabotError::ParseUrlError in case the `url` is not parsable
    ///   - CabotError::OpaqueUrlError in case the `url` is parsed but miss informations such as hostname.
    ///
    pub fn build(&self) -> CabotResult<Request> {
        if let Err(ref err) = self.url {
            return Err(CabotError::UrlParseError(err.clone()));
        }
        let url = self.url.as_ref().unwrap().clone();

        let host = url.host_str();
        if host.is_none() {
            return Err(CabotError::OpaqueUrlError("Unable to find host".to_string()));
        }
        let host = host.unwrap();

        let port = url.port_or_known_default();
        if port.is_none() {
            return Err(CabotError::OpaqueUrlError("Unable to determine a port".to_string()));
        }
        let port = port.unwrap();

        let query = url.query();
        let mut request_uri = url.path().to_owned();
        if let Some(querystring) = query {
            request_uri.push_str("?");
            request_uri.push_str(querystring);
        }
        let mut is_domain = true;
        if url.domain().is_none() {
            is_domain = false;
        }

        Ok(Request::new(host.to_owned(),
                        port,
                        format!("{}:{}", host, port),
                        is_domain,
                        url.scheme().to_owned(),
                        self.http_method.clone(),
                        request_uri,
                        self.http_version.clone(),
                        self.headers.clone(),
                        match self.body {
                            Some(ref body) => Some(body.clone()),
                            None => None,
                        }))
    }
}

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

    #[test]
    fn test_get_request_to_string() {
        let request = Request::new("127.0.0.1".to_owned(),
                                   80,
                                   "127.0.0.1:80".to_owned(),
                                   false,
                                   "http".to_owned(),
                                   "GET".to_owned(),
                                   "/path?query".to_owned(),
                                   "HTTP/1.1".to_owned(),
                                   Vec::new(),
                                   None);
        let attempt = "GET /path?query HTTP/1.1\r\nConnection: close\r\n\r\n";
        assert_eq!(request.to_string(), attempt);
    }

    #[test]
    fn test_get_request_wiht_host_to_string() {
        let request = Request::new("localhost".to_owned(),
                                   80,
                                   "localhost:80".to_owned(),
                                   true,
                                   "http".to_owned(),
                                   "GET".to_owned(),
                                   "/path?query".to_owned(),
                                   "HTTP/1.1".to_owned(),
                                   Vec::new(),
                                   None);
        let attempt = "GET /path?query HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n";
        assert_eq!(request.to_string(), attempt);
    }

    #[test]
    fn test_get_request_with_headers_to_string() {
        let request = Request::new("localhost".to_owned(),
                                   80,
                                   "localhost:80".to_owned(),
                                   true,
                                   "http".to_owned(),
                                   "GET".to_owned(),
                                   "/path?query".to_owned(),
                                   "HTTP/1.1".to_owned(),
                                   vec!["Accept-Language: fr".to_owned(),
                                        "Accept-Encoding: gzip".to_owned()],
                                   None);
        let attempt = "GET /path?query HTTP/1.1\r\nAccept-Language: fr\r\nAccept-Encoding: \
                       gzip\r\nHost: localhost\r\nConnection: close\r\n\r\n";
        assert_eq!(request.to_string(), attempt);
    }

    #[test]
    fn test_post_request_with_headers_to_string() {
        let request = Request::new("localhost".to_owned(),
                                   80,
                                   "localhost:80".to_owned(),
                                   true,
                                   "http".to_owned(),
                                   "POST".to_owned(),
                                   "/".to_owned(),
                                   "HTTP/1.1".to_owned(),
                                   vec!["Accept-Language: fr".to_owned(),
                                        "Content-Type: application/json".to_owned()],
                                   Some("{}".to_owned()));
        let attempt = "POST / HTTP/1.1\r\nAccept-Language: fr\r\nContent-Type: \
                       application/json\r\nHost: localhost\r\nConnection: \
                       close\r\nContent-Length: 2\r\n\r\n{}";
        assert_eq!(request.to_string(), attempt);
    }

    #[test]
    fn test_request_builder_simple() {
        let request = RequestBuilder::new("http://localhost/")
            .build()
            .unwrap();
        assert_eq!(request.host(), "localhost".to_string());
        assert_eq!(request.scheme(), "http".to_string());
        assert_eq!(request.body, None);
        assert_eq!(request.http_method(), "GET".to_string());
        assert_eq!(request.http_version(), "HTTP/1.1".to_string());
        let headers: Vec<String> = Vec::new();
        assert_eq!(request.headers, headers);
    }

    #[test]
    fn test_request_builder_complete() {
        let builder = RequestBuilder::new("http://localhost/")
            .set_http_method("POST")
            .set_http_version("HTTP/1.0")
            .add_header("Content-Type: application/json")
            .add_headers(&["Accept-Encoding: deflate", "Accept-Language: fr"])
            .set_body("{}");
        let request = builder.build().unwrap();
        assert_eq!(request.host(), "localhost".to_string());
        assert_eq!(request.body, Some("{}".to_string()));
        assert_eq!(request.scheme(), "http".to_string());
        assert_eq!(request.http_method(), "POST".to_string());
        assert_eq!(request.request_uri(), "/");
        assert_eq!(request.http_version(), "HTTP/1.0".to_string());
        assert_eq!(request.headers,
                   vec!["Content-Type: application/json".to_string(),
                        "Accept-Encoding: deflate".to_string(),
                        "Accept-Language: fr".to_string()]);

        let builder = builder.set_url("http://[::1]/path");
        let request = builder.build().unwrap();
        assert_eq!(request.host(), "[::1]".to_string());
        assert_eq!(request.request_uri(), "/path");
        assert_eq!(request.body, Some("{}".to_string()));
        assert_eq!(request.scheme(), "http".to_string());
        assert_eq!(request.http_method(), "POST".to_string());
        assert_eq!(request.http_version(), "HTTP/1.0".to_string());
        assert_eq!(request.headers,
                   vec!["Content-Type: application/json".to_string(),
                        "Accept-Encoding: deflate".to_string(),
                        "Accept-Language: fr".to_string()]);

        let builder = builder.set_url("not_an_url");
        let err = builder.build();
        assert!(err.is_err());
    }

}
<commit_msg>Fix type of request body, must be a array of u8<commit_after>//! HTTP Request handling.
//!
//! # Example
//! ```
//! use cabot::RequestBuilder;
//!
//! let request = RequestBuilder::new("http://localhost/")
//!     .set_http_method("POST")
//!     .add_header("Content-Type: application/json")
//!     .set_body_as_str("{}")
//!     .build()
//!     .unwrap();
//!     let attempt = "POST / HTTP/1.1\r\nContent-Type: \
//!                    application/json\r\nHost: localhost\r\nConnection: \
//!                    close\r\nContent-Length: 2\r\n\r\n{}";
//! assert_eq!(request.to_string(), attempt.to_string());
//! ```

use url::{self, Url};

use results::{CabotResult, CabotError};

/// An HTTP Request representation.
///
/// Request is build using [RequestBuilder](../request/struct.RequestBuilder.html)
/// and them consume by the [Client](../client/struct.Client.html)
/// to perform the query.
pub struct Request {
    host: String,
    port: u16,
    authority: String,
    is_domain: bool,
    scheme: String,
    http_method: String,
    request_uri: String,
    http_version: String,
    headers: Vec<String>,
    body: Option<Vec<u8>>,
}

impl Request {
    fn new(host: String,
           port: u16,
           authority: String,
           is_domain: bool,
           scheme: String,
           http_method: String,
           request_uri: String,
           http_version: String,
           headers: Vec<String>,
           body: Option<Vec<u8>>)
           -> Request {
        Request {
            host: host,
            port: port,
            authority: authority,
            is_domain: is_domain,
            scheme: scheme,
            http_method: http_method,
            request_uri: request_uri,
            http_version: http_version,
            headers: headers,
            body: body,
        }
    }

    /// The HTTP verb used to perform the request,
    /// such as GET, POST, ...
    pub fn http_method(&self) -> &str {
        self.http_method.as_str()
    }

    /// The HTTP Body of the request.
    pub fn body(&self) -> Option<&[u8]> {
        match self.body {
            None => None,
            Some(ref body) => {
                Some(body.as_slice())
            }
        }
    }

    /// Clone the body and retrieve it in a String object.
    ///
    /// Important: Currently assume the body is encoded in utf-8.
    ///
    /// Errors:
    ///
    ///  - CabotError::EncodingError in case the body is not an utf-8 string
    ///
    pub fn body_as_string(&self) -> CabotResult<Option<String>> {
        let body = match self.body {
            None => return Ok(None),
            Some(ref body) => {
                let mut body_vec: Vec<u8> = Vec::new();
                body_vec.extend_from_slice(body);
                let body_str = String::from_utf8(body_vec);
                if body_str.is_err() {
                    return Err(CabotError::EncodingError(format!("Cannot decode utf8: {}", body_str.unwrap_err())))
                }
                body_str.unwrap()
            }
        };
        Ok(Some(body))
    }

    /// The Version of the HTTP to perform the request.
    pub fn http_version(&self) -> &str {
        self.http_version.as_str()
    }

    /// The server name to connect. can be a name to resolve or an IP address.
    pub fn host(&self) -> &str {
        self.host.as_str()
    }

    /// The TCP server port to connect.
    pub fn port(&self) -> u16 {
        self.port
    }

    /// The authority part of the url (`host`:`port`).
    pub fn authority(&self) -> &str {
        self.authority.as_str()
    }

    /// The protocol scheme, can be http or https.
    pub fn scheme(&self) -> &str {
        self.scheme.as_str()
    }

    /// The URI to send, something like a PATH_INFO and a querystring.
    pub fn request_uri(&self) -> &str {
        self.request_uri.as_str()
    }

    /// The String representation of the query to send to the server.
    pub fn to_string(&self) -> String {
        let mut resp = format!("{} {} {}\r\n",
                               self.http_method(),
                               self.request_uri(),
                               self.http_version());
        if self.headers.len() > 0 {
            resp.push_str(self.headers.as_slice().join("\r\n").as_str());
            resp.push_str("\r\n");
        }
        if self.is_domain {
            resp.push_str(format!("Host: {}\r\n", self.host()).as_str());
        }
        resp.push_str("Connection: close\r\n");
        if let Ok(Some(payload)) = self.body_as_string() {
            resp.push_str(format!("Content-Length: {}\r\n", payload.len()).as_str());
            resp.push_str("\r\n");
            resp.push_str(payload.as_str());
        } else {
            resp.push_str("\r\n");
        }
        resp
    }
}

/// Construct [Request](../request/struct.Request.html)
pub struct RequestBuilder {
    http_method: String,
    url: Result<Url, url::ParseError>,
    http_version: String,
    headers: Vec<String>,
    body: Option<Vec<u8>>,
}

impl RequestBuilder {
    /// Create a new RequestBuilder with the given url.
    ///
    /// `url` will be parsed to get the host to contact and the uri to send.
    /// When building a request object after creating the builder,
    /// the http method will be `GET` with neither header nor body and
    /// the http version will be `HTTP/1.1`
    pub fn new(url: &str) -> Self {
        let url = url.parse::<Url>();
        RequestBuilder {
            http_method: "GET".to_owned(),
            url: url,
            http_version: "HTTP/1.1".to_owned(),
            headers: Vec::new(),
            body: None,
        }
    }

    /// Replace the url in case the RequestBuilder is used many time
    /// for multiple query.
    pub fn set_url(mut self, url: &str) -> Self {
        self.url = url.parse::<Url>();
        self
    }

    /// Set the http method such as `GET` `POST`. Default value is `GET`.
    pub fn set_http_method(mut self, http_method: &str) -> Self {
        self.http_method = http_method.to_owned();
        self
    }

    /// Set the protocol version to use.. Default value is `HTTP/1.1`.
    pub fn set_http_version(mut self, http_version: &str) -> Self {
        self.http_version = http_version.to_owned();
        self
    }

    /// Add a HTTP header.
    pub fn add_header(mut self, header: &str) -> Self {
        self.headers.push(header.to_owned());
        self
    }

    /// Add many headers.
    pub fn add_headers(mut self, headers: &[&str]) -> Self {
        for header in headers {
            self.headers.push(header.to_string());
        }
        self
    }

    /// Set a response body
    pub fn set_body(mut self, buf: &[u8]) -> Self {
        let mut body = Vec::with_capacity(buf.len());
        body.extend_from_slice(buf);
        self.body = Some(body);
        self
    }

    /// Set a body to send in the query. By default a query has no body.
    pub fn set_body_as_str(self, body: &str) -> Self {
        let moved = self.set_body(body.as_bytes());
        moved
    }

    /// Construct the [Request](../request/struct.Request.html).
    /// To perform the query, a [Client](../client/struct.Client.html)
    /// has to be created.
    ///
    /// Errors:
    ///
    ///   - CabotError::ParseUrlError in case the `url` is not parsable
    ///   - CabotError::OpaqueUrlError in case the `url` is parsed but miss informations such as hostname.
    ///
    pub fn build(&self) -> CabotResult<Request> {
        if let Err(ref err) = self.url {
            return Err(CabotError::UrlParseError(err.clone()));
        }
        let url = self.url.as_ref().unwrap().clone();

        let host = url.host_str();
        if host.is_none() {
            return Err(CabotError::OpaqueUrlError("Unable to find host".to_string()));
        }
        let host = host.unwrap();

        let port = url.port_or_known_default();
        if port.is_none() {
            return Err(CabotError::OpaqueUrlError("Unable to determine a port".to_string()));
        }
        let port = port.unwrap();

        let query = url.query();
        let mut request_uri = url.path().to_owned();
        if let Some(querystring) = query {
            request_uri.push_str("?");
            request_uri.push_str(querystring);
        }
        let mut is_domain = true;
        if url.domain().is_none() {
            is_domain = false;
        }

        Ok(Request::new(host.to_owned(),
                        port,
                        format!("{}:{}", host, port),
                        is_domain,
                        url.scheme().to_owned(),
                        self.http_method.clone(),
                        request_uri,
                        self.http_version.clone(),
                        self.headers.clone(),
                        match self.body {
                            Some(ref body) => Some(body.clone()),
                            None => None,
                        }))
    }
}

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

    #[test]
    fn test_get_request_to_string() {
        let request = Request::new("127.0.0.1".to_owned(),
                                   80,
                                   "127.0.0.1:80".to_owned(),
                                   false,
                                   "http".to_owned(),
                                   "GET".to_owned(),
                                   "/path?query".to_owned(),
                                   "HTTP/1.1".to_owned(),
                                   Vec::new(),
                                   None);
        let attempt = "GET /path?query HTTP/1.1\r\nConnection: close\r\n\r\n";
        assert_eq!(request.to_string(), attempt);
    }

    #[test]
    fn test_get_request_wiht_host_to_string() {
        let request = Request::new("localhost".to_owned(),
                                   80,
                                   "localhost:80".to_owned(),
                                   true,
                                   "http".to_owned(),
                                   "GET".to_owned(),
                                   "/path?query".to_owned(),
                                   "HTTP/1.1".to_owned(),
                                   Vec::new(),
                                   None);
        let attempt = "GET /path?query HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n";
        assert_eq!(request.to_string(), attempt);
    }

    #[test]
    fn test_get_request_with_headers_to_string() {
        let request = Request::new("localhost".to_owned(),
                                   80,
                                   "localhost:80".to_owned(),
                                   true,
                                   "http".to_owned(),
                                   "GET".to_owned(),
                                   "/path?query".to_owned(),
                                   "HTTP/1.1".to_owned(),
                                   vec!["Accept-Language: fr".to_owned(),
                                        "Accept-Encoding: gzip".to_owned()],
                                   None);
        let attempt = "GET /path?query HTTP/1.1\r\nAccept-Language: fr\r\nAccept-Encoding: \
                       gzip\r\nHost: localhost\r\nConnection: close\r\n\r\n";
        assert_eq!(request.to_string(), attempt);
    }

    #[test]
    fn test_post_request_with_headers_to_string() {
        let body: Vec<u8> = vec![123, 125];
        let request = Request::new("localhost".to_owned(),
                                   80,
                                   "localhost:80".to_owned(),
                                   true,
                                   "http".to_owned(),
                                   "POST".to_owned(),
                                   "/".to_owned(),
                                   "HTTP/1.1".to_owned(),
                                   vec!["Accept-Language: fr".to_owned(),
                                        "Content-Type: application/json".to_owned()],
                                   Some(body));
        let attempt = "POST / HTTP/1.1\r\nAccept-Language: fr\r\nContent-Type: \
                       application/json\r\nHost: localhost\r\nConnection: \
                       close\r\nContent-Length: 2\r\n\r\n{}";
        assert_eq!(request.to_string(), attempt);
    }

    #[test]
    fn test_request_builder_simple() {
        let request = RequestBuilder::new("http://localhost/")
            .build()
            .unwrap();
        assert_eq!(request.host(), "localhost".to_string());
        assert_eq!(request.scheme(), "http".to_string());
        assert_eq!(request.body, None);
        assert_eq!(request.http_method(), "GET".to_string());
        assert_eq!(request.http_version(), "HTTP/1.1".to_string());
        let headers: Vec<String> = Vec::new();
        assert_eq!(request.headers, headers);
    }

    #[test]
    fn test_request_builder_complete() {
        let builder = RequestBuilder::new("http://localhost/")
            .set_http_method("POST")
            .set_http_version("HTTP/1.0")
            .add_header("Content-Type: application/json")
            .add_headers(&["Accept-Encoding: deflate", "Accept-Language: fr"])
            .set_body_as_str("{}");
        let body: &[u8] = &[123, 125];
        let request = builder.build().unwrap();
        assert_eq!(request.host(), "localhost".to_string());
        assert_eq!(request.body(), Some(body));
        assert_eq!(request.body_as_string().unwrap().unwrap(), "{}".to_string());
        assert_eq!(request.scheme(), "http".to_string());
        assert_eq!(request.http_method(), "POST".to_string());
        assert_eq!(request.request_uri(), "/");
        assert_eq!(request.http_version(), "HTTP/1.0".to_string());
        assert_eq!(request.headers,
                   vec!["Content-Type: application/json".to_string(),
                        "Accept-Encoding: deflate".to_string(),
                        "Accept-Language: fr".to_string()]);

        let builder = builder.set_url("http://[::1]/path");
        let request = builder.build().unwrap();
        assert_eq!(request.host(), "[::1]".to_string());
        assert_eq!(request.request_uri(), "/path");
        assert_eq!(request.body(), Some(body));
        assert_eq!(request.body_as_string().unwrap().unwrap(), "{}".to_string());
        assert_eq!(request.scheme(), "http".to_string());
        assert_eq!(request.http_method(), "POST".to_string());
        assert_eq!(request.http_version(), "HTTP/1.0".to_string());
        assert_eq!(request.headers,
                   vec!["Content-Type: application/json".to_string(),
                        "Accept-Encoding: deflate".to_string(),
                        "Accept-Language: fr".to_string()]);

        let builder = builder.set_url("not_an_url");
        let err = builder.build();
        assert!(err.is_err());
    }

}
<|endoftext|>