<commit_before>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Build hooks to spit out version+build time info

use built;

use reqwest;

use flate2::read::GzDecoder;
use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::io::Read;
use std::path::{self, Path, PathBuf};
use std::process::Command;

use tar::Archive;

const WEB_WALLET_TAG: &str = "0.3.0.1";

fn main() {
	// Setting up git hooks in the project: rustfmt and so on.
	let git_hooks = format!(
		"git config core.hooksPath {}",
		PathBuf::from("./.hooks").to_str().unwrap()
	);

	if cfg!(target_os = "windows") {
		Command::new("cmd")
			.args(&["/C", &git_hooks])
			.output()
			.expect("failed to execute git config for hooks");
	} else {
		Command::new("sh")
			.args(&["-c", &git_hooks])
			.output()
			.expect("failed to execute git config for hooks");
	}

	// build and versioning information
	let mut opts = built::Options::default();
	opts.set_dependencies(true);
	// don't fail the build if something's missing, may just be cargo release
	let _ = built::write_built_file_with_opts(
		&opts,
		env!("CARGO_MANIFEST_DIR"),
		format!("{}{}", env::var("OUT_DIR").unwrap(), "/built.rs"),
	);

	install_web_wallet();
}

fn download_and_decompress(target_file: &str) {
	let req_path = format!("https://github.com/mimblewimble/grin-web-wallet/releases/download/{}/grin-web-wallet.tar.gz", WEB_WALLET_TAG);
	let resp = reqwest::get(&req_path);

	// don't interfere if this doesn't work
	if resp.is_err() {
		println!("Warning: Failed to download grin-web-wallet. Web wallet will not be available");
		return;
	}

	let mut resp = resp.unwrap();
	if resp.status().is_success() {
		// read response
		let mut out: Vec<u8> = vec![];
		let r2 = resp.read_to_end(&mut out);
		if r2.is_err() {
			println!(
				"Warning: Failed to download grin-web-wallet. Web wallet will not be available"
			);
			return;
		}

		// Gunzip
		let mut d = GzDecoder::new(&out[..]);
		let mut decomp: Vec<u8> = vec![];
		d.read_to_end(&mut decomp).unwrap();

		// write temp file
		let mut buffer = File::create(target_file.clone()).unwrap();
		buffer.write_all(&decomp).unwrap();
		buffer.flush().unwrap();
	}
}

/// Download and unzip tagged web-wallet build
fn install_web_wallet() {
	let target_file = format!(
		"{}/grin-web-wallet-{}.tar",
		env::var("OUT_DIR").unwrap(),
		WEB_WALLET_TAG
	);
	let out_dir = env::var("OUT_DIR").unwrap();
	let mut out_path = PathBuf::from(&out_dir);
	out_path.pop();
	out_path.pop();
	out_path.pop();

	// only re-download if needed
	if !Path::new(&target_file).is_file() {
		download_and_decompress(&target_file);
	}

	// remove old version
	let mut remove_path = out_path.clone();
	remove_path.push("grin-wallet");
	let _ = fs::remove_dir_all(remove_path);

	// Untar
	let file = File::open(target_file).unwrap();
	let mut a = Archive::new(file);

	for file in a.entries().unwrap() {
		let mut file = file.unwrap();
		let h = file.header().clone();
		let path = h.path().unwrap().clone().into_owned();
		let is_dir = path.to_str().unwrap().ends_with(path::MAIN_SEPARATOR);
		let path = path.strip_prefix("dist").unwrap();
		let mut final_path = out_path.clone();
		final_path.push(path);

		let mut tmp: Vec<u8> = vec![];
		file.read_to_end(&mut tmp).unwrap();
		if is_dir {
			fs::create_dir_all(final_path).unwrap();
		} else {
			let mut buffer = File::create(final_path).unwrap();
			buffer.write_all(&tmp).unwrap();
			buffer.flush().unwrap();
		}
	}
}
<commit_msg>offline build not possible right now closes #2139 (#2141)<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Build hooks to spit out version+build time info

use built;

use reqwest;

use flate2::read::GzDecoder;
use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::io::Read;
use std::path::{self, Path, PathBuf};
use std::process::Command;

use tar::Archive;

const WEB_WALLET_TAG: &str = "0.3.0.1";

fn main() {
	// Setting up git hooks in the project: rustfmt and so on.
	let git_hooks = format!(
		"git config core.hooksPath {}",
		PathBuf::from("./.hooks").to_str().unwrap()
	);

	if cfg!(target_os = "windows") {
		Command::new("cmd")
			.args(&["/C", &git_hooks])
			.output()
			.expect("failed to execute git config for hooks");
	} else {
		Command::new("sh")
			.args(&["-c", &git_hooks])
			.output()
			.expect("failed to execute git config for hooks");
	}

	// build and versioning information
	let mut opts = built::Options::default();
	opts.set_dependencies(true);
	// don't fail the build if something's missing, may just be cargo release
	let _ = built::write_built_file_with_opts(
		&opts,
		env!("CARGO_MANIFEST_DIR"),
		format!("{}{}", env::var("OUT_DIR").unwrap(), "/built.rs"),
	);

	let web_wallet_install = install_web_wallet();
	match web_wallet_install {
		Ok(true) => {}
		_ => println!(
			"WARNING : Web wallet could not be installed due to {:?}",
			web_wallet_install
		),
	}
}

fn download_and_decompress(target_file: &str) -> Result<bool, Box<std::error::Error>> {
	let req_path = format!("https://github.com/mimblewimble/grin-web-wallet/releases/download/{}/grin-web-wallet.tar.gz", WEB_WALLET_TAG);
	let mut resp = reqwest::get(&req_path)?;

	if !resp.status().is_success() {
		return Ok(false);
	}

	// read response
	let mut out: Vec<u8> = vec![];
	resp.read_to_end(&mut out)?;

	// Gunzip
	let mut d = GzDecoder::new(&out[..]);
	let mut decomp: Vec<u8> = vec![];
	d.read_to_end(&mut decomp)?;

	// write temp file
	let mut buffer = File::create(target_file.clone())?;
	buffer.write_all(&decomp)?;
	buffer.flush()?;

	Ok(true)
}

/// Download and unzip tagged web-wallet build
fn install_web_wallet() -> Result<bool, Box<std::error::Error>> {
	let target_file = format!(
		"{}/grin-web-wallet-{}.tar",
		env::var("OUT_DIR")?,
		WEB_WALLET_TAG
	);
	let out_dir = env::var("OUT_DIR")?;
	let mut out_path = PathBuf::from(&out_dir);
	out_path.pop();
	out_path.pop();
	out_path.pop();

	// only re-download if needed
	println!("{}", target_file);
	if !Path::new(&target_file).is_file() {
		let success = download_and_decompress(&target_file)?;
		if !success {
			return Ok(false); // could not download and decompress
		}
	}

	// remove old version
	let mut remove_path = out_path.clone();
	remove_path.push("grin-wallet");
	let _ = fs::remove_dir_all(remove_path);

	// Untar
	let file = File::open(target_file)?;
	let mut a = Archive::new(file);

	for file in a.entries()? {
		let mut file = file?;
		let h = file.header().clone();
		let path = h.path()?.clone().into_owned();
		let is_dir = path.to_str().unwrap().ends_with(path::MAIN_SEPARATOR);
		let path = path.strip_prefix("dist")?;
		let mut final_path = out_path.clone();
		final_path.push(path);

		let mut tmp: Vec<u8> = vec![];
		file.read_to_end(&mut tmp)?;
		if is_dir {
			fs::create_dir_all(final_path)?;
		} else {
			let mut buffer = File::create(final_path)?;
			buffer.write_all(&tmp)?;
			buffer.flush()?;
		}
	}

	Ok(true)
}
<|endoftext|>


<commit_before>//! Combinators applying parsers in sequence

#[macro_use]
mod macros;

use crate::error::ParseError;
use crate::internal::{IResult, Parser};

/// Gets an object from the first parser,
/// then gets another object from the second parser.
///
/// # Arguments
/// * `first` The first parser to apply.
/// * `second` The second parser to apply.
/// ```rust
/// # use nom::{Err, error::ErrorKind, Needed};
/// # use nom::Needed::Size;
/// use nom::sequence::pair;
/// use nom::bytes::complete::tag;
///
/// let mut parser = pair(tag("abc"), tag("efg"));
///
/// assert_eq!(parser("abcefg"), Ok(("", ("abc", "efg"))));
/// assert_eq!(parser("abcefghij"), Ok(("hij", ("abc", "efg"))));
/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
/// ```
pub fn pair<I, O1, O2, E: ParseError<I>, F, G>(
  mut first: F,
  mut second: G,
) -> impl FnMut(I) -> IResult<I, (O1, O2), E>
where
  F: Parser<I, O1, E>,
  G: Parser<I, O2, E>,
{
  move |input: I| {
    let (input, o1) = first.parse(input)?;
    second.parse(input).map(|(i, o2)| (i, (o1, o2)))
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn pairc<I, O1, O2, E: ParseError<I>, F, G>(
  input: I,
  first: F,
  second: G,
) -> IResult<I, (O1, O2), E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  pair(first, second)(input)
}

/// Matches an object from the first parser and discards it,
/// then gets an object from the second parser.
///
/// # Arguments
/// * `first` The opening parser.
/// * `second` The second parser to get object.
/// ```rust
/// # use nom::{Err, error::ErrorKind, Needed};
/// # use nom::Needed::Size;
/// use nom::sequence::preceded;
/// use nom::bytes::complete::tag;
///
/// let mut parser = preceded(tag("abc"), tag("efg"));
///
/// assert_eq!(parser("abcefg"), Ok(("", "efg")));
/// assert_eq!(parser("abcefghij"), Ok(("hij", "efg")));
/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
/// ```
pub fn preceded<I, O1, O2, E: ParseError<I>, F, G>(
  mut first: F,
  mut second: G,
) -> impl FnMut(I) -> IResult<I, O2, E>
where
  F: Parser<I, O1, E>,
  G: Parser<I, O2, E>,
{
  move |input: I| {
    let (input, _) = first.parse(input)?;
    second.parse(input)
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn precededc<I, O1, O2, E: ParseError<I>, F, G>(
  input: I,
  first: F,
  second: G,
) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  preceded(first, second)(input)
}

/// Gets an object from the first parser,
/// then matches an object from the second parser and discards it.
///
/// # Arguments
/// * `first` The first parser to apply.
/// * `second` The second parser to match an object.
/// ```rust
/// # use nom::{Err, error::ErrorKind, Needed};
/// # use nom::Needed::Size;
/// use nom::sequence::terminated;
/// use nom::bytes::complete::tag;
///
/// let mut parser = terminated(tag("abc"), tag("efg"));
///
/// assert_eq!(parser("abcefg"), Ok(("", "abc")));
/// assert_eq!(parser("abcefghij"), Ok(("hij", "abc")));
/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
/// ```
pub fn terminated<I, O1, O2, E: ParseError<I>, F, G>(
  mut first: F,
  mut second: G,
) -> impl FnMut(I) -> IResult<I, O1, E>
where
  F: Parser<I, O1, E>,
  G: Parser<I, O2, E>,
{
  move |input: I| {
    let (input, o1) = first.parse(input)?;
    second.parse(input).map(|(i, _)| (i, o1))
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn terminatedc<I, O1, O2, E: ParseError<I>, F, G>(
  input: I,
  first: F,
  second: G,
) -> IResult<I, O1, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  terminated(first, second)(input)
}

/// Gets an object from the first parser,
/// then matches an object from the sep_parser and discards it,
/// then gets another object from the second parser.
///
/// # Arguments
/// * `first` The first parser to apply.
/// * `sep` The separator parser to apply.
/// * `second` The second parser to apply.
/// ```rust
/// # use nom::{Err, error::ErrorKind, Needed};
/// # use nom::Needed::Size;
/// use nom::sequence::separated_pair;
/// use nom::bytes::complete::tag;
///
/// let mut parser = separated_pair(tag("abc"), tag("|"), tag("efg"));
///
/// assert_eq!(parser("abc|efg"), Ok(("", ("abc", "efg"))));
/// assert_eq!(parser("abc|efghij"), Ok(("hij", ("abc", "efg"))));
/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
/// ```
pub fn separated_pair<I, O1, O2, O3, E: ParseError<I>, F, G, H>(
  mut first: F,
  mut sep: G,
  mut second: H,
) -> impl FnMut(I) -> IResult<I, (O1, O3), E>
where
  F: Parser<I, O1, E>,
  G: Parser<I, O2, E>,
  H: Parser<I, O3, E>,
{
  move |input: I| {
    let (input, o1) = first.parse(input)?;
    let (input, _) = sep.parse(input)?;
    second.parse(input).map(|(i, o2)| (i, (o1, o2)))
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn separated_pairc<I, O1, O2, O3, E: ParseError<I>, F, G, H>(
  input: I,
  first: F,
  sep: G,
  second: H,
) -> IResult<I, (O1, O3), E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
  H: Fn(I) -> IResult<I, O3, E>,
{
  separated_pair(first, sep, second)(input)
}

/// Matches an object from the first parser,
/// then gets an object from the sep_parser,
/// then matches another object from the second parser.
///
/// # Arguments
/// * `first` The first parser to apply.
/// * `sep` The separator parser to apply.
/// * `second` The second parser to apply.
/// ```rust
/// # use nom::{Err, error::ErrorKind, Needed};
/// # use nom::Needed::Size;
/// use nom::sequence::delimited;
/// use nom::bytes::complete::tag;
///
/// let mut parser = delimited(tag("abc"), tag("|"), tag("efg"));
///
/// assert_eq!(parser("abc|efg"), Ok(("", "|")));
/// assert_eq!(parser("abc|efghij"), Ok(("hij", "|")));
/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
/// ```
pub fn delimited<I, O1, O2, O3, E: ParseError<I>, F, G, H>(
  mut first: F,
  mut sep: G,
  mut second: H,
) -> impl FnMut(I) -> IResult<I, O2, E>
where
  F: Parser<I, O1, E>,
  G: Parser<I, O2, E>,
  H: Parser<I, O3, E>,
{
  move |input: I| {
    let (input, _) = first.parse(input)?;
    let (input, o2) = sep.parse(input)?;
    second.parse(input).map(|(i, _)| (i, o2))
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn delimitedc<I, O1, O2, O3, E: ParseError<I>, F, G, H>(
  input: I,
  first: F,
  sep: G,
  second: H,
) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
  H: Fn(I) -> IResult<I, O3, E>,
{
  delimited(first, sep, second)(input)
}

/// Helper trait for the tuple combinator.
///
/// This trait is implemented for tuples of parsers of up to 21 elements.
pub trait Tuple<I, O, E> {
  /// Parses the input and returns a tuple of results of each parser.
  fn parse(&mut self, input: I) -> IResult<I, O, E>;
}

impl<Input, Output, Error: ParseError<Input>, F: Parser<Input, Output, Error>>
  Tuple<Input, (Output,), Error> for (F,)
{
  fn parse(&mut self, input: Input) -> IResult<Input, (Output,), Error> {
    self.0.parse(input).map(|(i, o)| (i, (o,)))
  }
}

macro_rules! tuple_trait(
  ($name1:ident $ty1:ident, $name2: ident $ty2:ident, $($name:ident $ty:ident),*) => (
    tuple_trait!(__impl $name1 $ty1, $name2 $ty2; $($name $ty),*);
  );
  (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident, $($name2:ident $ty2:ident),*) => (
    tuple_trait_impl!($($name $ty),+);
    tuple_trait!(__impl $($name $ty),+ , $name1 $ty1; $($name2 $ty2),*);
  );
  (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident) => (
    tuple_trait_impl!($($name $ty),+);
    tuple_trait_impl!($($name $ty),+, $name1 $ty1);
  );
);

macro_rules! tuple_trait_impl(
  ($($name:ident $ty: ident),+) => (
    impl<
      Input: Clone, $($ty),+ , Error: ParseError<Input>,
      $($name: Parser<Input, $ty, Error>),+
    > Tuple<Input, ( $($ty),+ ), Error> for ( $($name),+ ) {

      fn parse(&mut self, input: Input) -> IResult<Input, ( $($ty),+ ), Error> {
        tuple_trait_inner!(0, self, input, (), $($name)+)

      }
    }
  );
);

macro_rules! tuple_trait_inner(
  ($it:tt, $self:expr, $input:expr, (), $head:ident $($id:ident)+) => ({
    let (i, o) = $self.$it.parse($input.clone())?;

    succ!($it, tuple_trait_inner!($self, i, ( o ), $($id)+))
  });
  ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident $($id:ident)+) => ({
    let (i, o) = $self.$it.parse($input.clone())?;

    succ!($it, tuple_trait_inner!($self, i, ($($parsed)* , o), $($id)+))
  });
  ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident) => ({
    let (i, o) = $self.$it.parse($input.clone())?;

    Ok((i, ($($parsed)* , o)))
  });
);

tuple_trait!(FnA A, FnB B, FnC C, FnD D, FnE E, FnF F, FnG G, FnH H, FnI I, FnJ J, FnK K, FnL L,
  FnM M, FnN N, FnO O, FnP P, FnQ Q, FnR R, FnS S, FnT T, FnU U);

///Applies a tuple of parsers one by one and returns their results as a tuple.
///
/// ```rust
/// # use nom::{Err, error::ErrorKind};
/// use nom::sequence::tuple;
/// use nom::character::complete::{alpha1, digit1};
/// let mut parser = tuple((alpha1, digit1, alpha1));
///
/// assert_eq!(parser("abc123def"), Ok(("", ("abc", "123", "def"))));
/// assert_eq!(parser("123def"), Err(Err::Error(("123def", ErrorKind::Alpha))));
/// ```
pub fn tuple<I, O, E: ParseError<I>, List: Tuple<I, O, E>>(
  mut l: List,
) -> impl FnMut(I) -> IResult<I, O, E> {
  move |i: I| l.parse(i)
}

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

  #[test]
  fn single_element_tuples() {
    use crate::character::complete::alpha1;
    use crate::{error::ErrorKind, Err};

    let mut parser = tuple((alpha1,));
    assert_eq!(parser("abc123def"), Ok(("123def", ("abc",))));
    assert_eq!(
      parser("123def"),
      Err(Err::Error(("123def", ErrorKind::Alpha)))
    );
  }
}
<commit_msg>Make documentation for delimited less confusing<commit_after>//! Combinators applying parsers in sequence

#[macro_use]
mod macros;

use crate::error::ParseError;
use crate::internal::{IResult, Parser};

/// Gets an object from the first parser,
/// then gets another object from the second parser.
///
/// # Arguments
/// * `first` The first parser to apply.
/// * `second` The second parser to apply.
/// ```rust
/// # use nom::{Err, error::ErrorKind, Needed};
/// # use nom::Needed::Size;
/// use nom::sequence::pair;
/// use nom::bytes::complete::tag;
///
/// let mut parser = pair(tag("abc"), tag("efg"));
///
/// assert_eq!(parser("abcefg"), Ok(("", ("abc", "efg"))));
/// assert_eq!(parser("abcefghij"), Ok(("hij", ("abc", "efg"))));
/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
/// ```
pub fn pair<I, O1, O2, E: ParseError<I>, F, G>(
  mut first: F,
  mut second: G,
) -> impl FnMut(I) -> IResult<I, (O1, O2), E>
where
  F: Parser<I, O1, E>,
  G: Parser<I, O2, E>,
{
  move |input: I| {
    let (input, o1) = first.parse(input)?;
    second.parse(input).map(|(i, o2)| (i, (o1, o2)))
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn pairc<I, O1, O2, E: ParseError<I>, F, G>(
  input: I,
  first: F,
  second: G,
) -> IResult<I, (O1, O2), E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  pair(first, second)(input)
}

/// Matches an object from the first parser and discards it,
/// then gets an object from the second parser.
///
/// # Arguments
/// * `first` The opening parser.
/// * `second` The second parser to get object.
/// ```rust
/// # use nom::{Err, error::ErrorKind, Needed};
/// # use nom::Needed::Size;
/// use nom::sequence::preceded;
/// use nom::bytes::complete::tag;
///
/// let mut parser = preceded(tag("abc"), tag("efg"));
///
/// assert_eq!(parser("abcefg"), Ok(("", "efg")));
/// assert_eq!(parser("abcefghij"), Ok(("hij", "efg")));
/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
/// ```
pub fn preceded<I, O1, O2, E: ParseError<I>, F, G>(
  mut first: F,
  mut second: G,
) -> impl FnMut(I) -> IResult<I, O2, E>
where
  F: Parser<I, O1, E>,
  G: Parser<I, O2, E>,
{
  move |input: I| {
    let (input, _) = first.parse(input)?;
    second.parse(input)
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn precededc<I, O1, O2, E: ParseError<I>, F, G>(
  input: I,
  first: F,
  second: G,
) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  preceded(first, second)(input)
}

/// Gets an object from the first parser,
/// then matches an object from the second parser and discards it.
///
/// # Arguments
/// * `first` The first parser to apply.
/// * `second` The second parser to match an object.
/// ```rust
/// # use nom::{Err, error::ErrorKind, Needed};
/// # use nom::Needed::Size;
/// use nom::sequence::terminated;
/// use nom::bytes::complete::tag;
///
/// let mut parser = terminated(tag("abc"), tag("efg"));
///
/// assert_eq!(parser("abcefg"), Ok(("", "abc")));
/// assert_eq!(parser("abcefghij"), Ok(("hij", "abc")));
/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
/// ```
pub fn terminated<I, O1, O2, E: ParseError<I>, F, G>(
  mut first: F,
  mut second: G,
) -> impl FnMut(I) -> IResult<I, O1, E>
where
  F: Parser<I, O1, E>,
  G: Parser<I, O2, E>,
{
  move |input: I| {
    let (input, o1) = first.parse(input)?;
    second.parse(input).map(|(i, _)| (i, o1))
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn terminatedc<I, O1, O2, E: ParseError<I>, F, G>(
  input: I,
  first: F,
  second: G,
) -> IResult<I, O1, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  terminated(first, second)(input)
}

/// Gets an object from the first parser,
/// then matches an object from the sep_parser and discards it,
/// then gets another object from the second parser.
///
/// # Arguments
/// * `first` The first parser to apply.
/// * `sep` The separator parser to apply.
/// * `second` The second parser to apply.
/// ```rust
/// # use nom::{Err, error::ErrorKind, Needed};
/// # use nom::Needed::Size;
/// use nom::sequence::separated_pair;
/// use nom::bytes::complete::tag;
///
/// let mut parser = separated_pair(tag("abc"), tag("|"), tag("efg"));
///
/// assert_eq!(parser("abc|efg"), Ok(("", ("abc", "efg"))));
/// assert_eq!(parser("abc|efghij"), Ok(("hij", ("abc", "efg"))));
/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
/// ```
pub fn separated_pair<I, O1, O2, O3, E: ParseError<I>, F, G, H>(
  mut first: F,
  mut sep: G,
  mut second: H,
) -> impl FnMut(I) -> IResult<I, (O1, O3), E>
where
  F: Parser<I, O1, E>,
  G: Parser<I, O2, E>,
  H: Parser<I, O3, E>,
{
  move |input: I| {
    let (input, o1) = first.parse(input)?;
    let (input, _) = sep.parse(input)?;
    second.parse(input).map(|(i, o2)| (i, (o1, o2)))
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn separated_pairc<I, O1, O2, O3, E: ParseError<I>, F, G, H>(
  input: I,
  first: F,
  sep: G,
  second: H,
) -> IResult<I, (O1, O3), E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
  H: Fn(I) -> IResult<I, O3, E>,
{
  separated_pair(first, sep, second)(input)
}

/// Matches an object from the first parser and discards it,
/// then gets an object from the second parser,
/// and finally matches an object from the third parser and discards it.
///
/// # Arguments
/// * `first` The first parser to apply and discard.
/// * `second` The second parser to apply.
/// * `third` The third parser to apply and discard.
/// ```rust
/// # use nom::{Err, error::ErrorKind, Needed};
/// # use nom::Needed::Size;
/// use nom::sequence::delimited;
/// use nom::bytes::complete::tag;
///
/// let mut parser = delimited(tag("("), tag("abc"), tag(")"));
///
/// assert_eq!(parser("(abc)"), Ok(("", "abc")));
/// assert_eq!(parser("(abc)def"), Ok(("def", "abc")));
/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
/// ```
pub fn delimited<I, O1, O2, O3, E: ParseError<I>, F, G, H>(
  mut first: F,
  mut second: G,
  mut third: H,
) -> impl FnMut(I) -> IResult<I, O2, E>
where
  F: Parser<I, O1, E>,
  G: Parser<I, O2, E>,
  H: Parser<I, O3, E>,
{
  move |input: I| {
    let (input, _) = first.parse(input)?;
    let (input, o2) = second.parse(input)?;
    third.parse(input).map(|(i, _)| (i, o2))
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn delimitedc<I, O1, O2, O3, E: ParseError<I>, F, G, H>(
  input: I,
  first: F,
  second: G,
  third: H,
) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
  H: Fn(I) -> IResult<I, O3, E>,
{
  delimited(first, second, third)(input)
}

/// Helper trait for the tuple combinator.
///
/// This trait is implemented for tuples of parsers of up to 21 elements.
pub trait Tuple<I, O, E> {
  /// Parses the input and returns a tuple of results of each parser.
  fn parse(&mut self, input: I) -> IResult<I, O, E>;
}

impl<Input, Output, Error: ParseError<Input>, F: Parser<Input, Output, Error>>
  Tuple<Input, (Output,), Error> for (F,)
{
  fn parse(&mut self, input: Input) -> IResult<Input, (Output,), Error> {
    self.0.parse(input).map(|(i, o)| (i, (o,)))
  }
}

macro_rules! tuple_trait(
  ($name1:ident $ty1:ident, $name2: ident $ty2:ident, $($name:ident $ty:ident),*) => (
    tuple_trait!(__impl $name1 $ty1, $name2 $ty2; $($name $ty),*);
  );
  (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident, $($name2:ident $ty2:ident),*) => (
    tuple_trait_impl!($($name $ty),+);
    tuple_trait!(__impl $($name $ty),+ , $name1 $ty1; $($name2 $ty2),*);
  );
  (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident) => (
    tuple_trait_impl!($($name $ty),+);
    tuple_trait_impl!($($name $ty),+, $name1 $ty1);
  );
);

macro_rules! tuple_trait_impl(
  ($($name:ident $ty: ident),+) => (
    impl<
      Input: Clone, $($ty),+ , Error: ParseError<Input>,
      $($name: Parser<Input, $ty, Error>),+
    > Tuple<Input, ( $($ty),+ ), Error> for ( $($name),+ ) {

      fn parse(&mut self, input: Input) -> IResult<Input, ( $($ty),+ ), Error> {
        tuple_trait_inner!(0, self, input, (), $($name)+)

      }
    }
  );
);

macro_rules! tuple_trait_inner(
  ($it:tt, $self:expr, $input:expr, (), $head:ident $($id:ident)+) => ({
    let (i, o) = $self.$it.parse($input.clone())?;

    succ!($it, tuple_trait_inner!($self, i, ( o ), $($id)+))
  });
  ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident $($id:ident)+) => ({
    let (i, o) = $self.$it.parse($input.clone())?;

    succ!($it, tuple_trait_inner!($self, i, ($($parsed)* , o), $($id)+))
  });
  ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident) => ({
    let (i, o) = $self.$it.parse($input.clone())?;

    Ok((i, ($($parsed)* , o)))
  });
);

tuple_trait!(FnA A, FnB B, FnC C, FnD D, FnE E, FnF F, FnG G, FnH H, FnI I, FnJ J, FnK K, FnL L,
  FnM M, FnN N, FnO O, FnP P, FnQ Q, FnR R, FnS S, FnT T, FnU U);

///Applies a tuple of parsers one by one and returns their results as a tuple.
///
/// ```rust
/// # use nom::{Err, error::ErrorKind};
/// use nom::sequence::tuple;
/// use nom::character::complete::{alpha1, digit1};
/// let mut parser = tuple((alpha1, digit1, alpha1));
///
/// assert_eq!(parser("abc123def"), Ok(("", ("abc", "123", "def"))));
/// assert_eq!(parser("123def"), Err(Err::Error(("123def", ErrorKind::Alpha))));
/// ```
pub fn tuple<I, O, E: ParseError<I>, List: Tuple<I, O, E>>(
  mut l: List,
) -> impl FnMut(I) -> IResult<I, O, E> {
  move |i: I| l.parse(i)
}

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

  #[test]
  fn single_element_tuples() {
    use crate::character::complete::alpha1;
    use crate::{error::ErrorKind, Err};

    let mut parser = tuple((alpha1,));
    assert_eq!(parser("abc123def"), Ok(("123def", ("abc",))));
    assert_eq!(
      parser("123def"),
      Err(Err::Error(("123def", ErrorKind::Alpha)))
    );
  }
}
<|endoftext|>


<commit_before>pub mod echo;
pub mod self_filter;

use self::echo::Echo;
use self::self_filter::SelfFilter;
<commit_msg>Remove use in service mod<commit_after>pub mod echo;
pub mod self_filter;
<|endoftext|>


<commit_before>use std::iter::{from_fn, FromIterator};

use indexmap::IndexSet;

use crate::{
    Direction::Outgoing,
    EdgeType,
    Graph,
    graph::IndexType,
    prelude::NodeIndex,
};

/// Returns iterator that produces all simple paths from `from` node to `to`, which contains at least `min_intermidiate_nodes` nodes
/// and at most `max_intermidiate_nodes`, if given, limited by graph's order otherwise
/// Simple path is path without repetitions
/// Algorithm is adopted from https://networkx.github.io/documentation/stable/reference/algorithms/generated/networkx.algorithms.simple_paths.all_simple_paths.html
pub fn all_simple_paths<'g, TargetIter: 'g, N, E, Ty, Ix>(graph: &'g Graph<N, E, Ty, Ix>,
                                                      from: NodeIndex<Ix>,
                                                      to: NodeIndex<Ix>,
                                                      min_intermidiate_nodes: usize,
                                                      max_intermidiate_nodes: Option<usize>) -> impl Iterator<Item=TargetIter> + 'g
    where Ix: IndexType, Ty: EdgeType, TargetIter: FromIterator<NodeIndex<Ix>>
{
    // how many nodes are allowed in simple path up to target node
    // it is min/max allowed path length minus one, because it is more appropriate when implementing lookahead
    // that constantly add 1 to length of current path
    let max_length = if let Some(l) = max_intermidiate_nodes {
        l + 1
    } else {
        graph.node_count() - 1
    };

    let min_length = min_intermidiate_nodes + 1;

    // list of visited nodes
    let mut visited: IndexSet<NodeIndex<Ix>> = IndexSet::from_iter(Some(from));
    // list of childs of currently exploring path nodes,
    // last elem is list of childs of last visited node
    let mut stack = vec![graph.neighbors_directed(from, Outgoing)];

    from_fn(move || {
        while let Some(children) = stack.last_mut() {
            if let Some(child) = children.next() {
                if visited.len() < max_length {
                    if child == to {
                        if visited.len() >= min_length {
                            let path = visited.iter().cloned().chain(Some(to)).collect::<TargetIter>();
                            return Some(path);
                        }
                    } else if !visited.contains(&child) {
                        visited.insert(child);
                        stack.push(graph.neighbors_directed(child, Outgoing));
                    }
                } else {
                    if (child == to || children.any(|v| v == to)) && visited.len() >= min_length {
                        let path = visited.iter().cloned().chain(Some(to)).collect::<TargetIter>();
                        return Some(path);
                    }
                    stack.pop();
                    visited.pop();
                }
            } else {
                stack.pop();
                visited.pop();
            }
        }
        None
    })
}

#[cfg(test)]
mod test {
    use itertools::equal;

    use crate::{
        dot::Dot,
        prelude::DiGraph,
    };

    use super::all_simple_paths;

    #[test]
    fn test_all_simple_paths() {
        let graph = DiGraph::<i32, i32, _>::from_edges(&[
            (0, 1),
            (0, 2),
            (0, 3),
            (1, 2),
            (1, 3),
            (2, 3),
            (2, 4),
            (3, 2),
            (3, 4),
            (4, 2),
            (4, 5),
            (5, 2),
            (5, 3)
        ]);

        let expexted_simple_paths_0_to_5 = &[
            vec![0usize, 1, 2, 3, 4, 5],
            vec![0, 1, 2, 4, 5],
            vec![0, 1, 3, 2, 4, 5],
            vec![0, 1, 3, 4, 5],
            vec![0, 2, 3, 4, 5],
            vec![0, 2, 4, 5],
            vec![0, 3, 2, 4, 5],
            vec![0, 3, 4, 5],
        ];

        println!("{}", Dot::new(&graph));
        let actual_simple_paths_0_to_5: Vec<Vec<_>> = all_simple_paths(&graph, 0u32.into(), 5u32.into(), 0, None)
            .map(|v: Vec<_>| v.into_iter().map(|i| i.index()).collect())
            .collect();
        println!("{:#?}", actual_simple_paths_0_to_5);
        assert_eq!(actual_simple_paths_0_to_5.len(), 8);
        equal(expexted_simple_paths_0_to_5, &actual_simple_paths_0_to_5);
    }

    #[test]
    fn test_one_simple_path() {
        let graph = DiGraph::<i32, i32, _>::from_edges(&[
            (0, 1),
            (2, 1)
        ]);

        let expexted_simple_paths_0_to_1 = &[
            vec![0usize, 1],
        ];
        println!("{}", Dot::new(&graph));
        let actual_simple_paths_0_to_1: Vec<Vec<_>> = all_simple_paths(&graph, 0u32.into(), 1u32.into(), 0, None)
            .map(|v: Vec<_>| v.into_iter().map(|i| i.index()).collect())
            .collect();

        println!("{:#?}", actual_simple_paths_0_to_1);
        assert_eq!(actual_simple_paths_0_to_1.len(), 1);
        equal(expexted_simple_paths_0_to_1, &actual_simple_paths_0_to_1);
    }

    #[test]
    fn test_no_simple_paths() {
        let graph = DiGraph::<i32, i32, _>::from_edges(&[
            (0, 1),
            (2, 1)
        ]);

        println!("{}", Dot::new(&graph));
        let actual_simple_paths_0_to_2: Vec<Vec<_>> = all_simple_paths(&graph, 0u32.into(), 2u32.into(), 0, None)
            .map(|v: Vec<_>| v.into_iter().map(|i| i.index()).collect())
            .collect();

        println!("{:#?}", actual_simple_paths_0_to_2);
        assert_eq!(actual_simple_paths_0_to_2.len(), 0);
    }
}
<commit_msg>Correctly test iterators equality Remove debug prints<commit_after>use std::iter::{from_fn, FromIterator};

use indexmap::IndexSet;

use crate::{
    Direction::Outgoing,
    EdgeType,
    Graph,
    graph::IndexType,
    prelude::NodeIndex,
};

/// Returns iterator that produces all simple paths from `from` node to `to`, which contains at least `min_intermidiate_nodes` nodes
/// and at most `max_intermidiate_nodes`, if given, limited by graph's order otherwise
/// Simple path is path without repetitions
/// Algorithm is adopted from https://networkx.github.io/documentation/stable/reference/algorithms/generated/networkx.algorithms.simple_paths.all_simple_paths.html
pub fn all_simple_paths<'g, TargetIter: 'g, N, E, Ty, Ix>(graph: &'g Graph<N, E, Ty, Ix>,
                                                          from: NodeIndex<Ix>,
                                                          to: NodeIndex<Ix>,
                                                          min_intermidiate_nodes: usize,
                                                          max_intermidiate_nodes: Option<usize>) -> impl Iterator<Item=TargetIter> + 'g
    where Ix: IndexType, Ty: EdgeType, TargetIter: FromIterator<NodeIndex<Ix>>
{
    // how many nodes are allowed in simple path up to target node
    // it is min/max allowed path length minus one, because it is more appropriate when implementing lookahead
    // that constantly add 1 to length of current path
    let max_length = if let Some(l) = max_intermidiate_nodes {
        l + 1
    } else {
        graph.node_count() - 1
    };

    let min_length = min_intermidiate_nodes + 1;

    // list of visited nodes
    let mut visited: IndexSet<NodeIndex<Ix>> = IndexSet::from_iter(Some(from));
    // list of childs of currently exploring path nodes,
    // last elem is list of childs of last visited node
    let mut stack = vec![graph.neighbors_directed(from, Outgoing)];

    from_fn(move || {
        while let Some(children) = stack.last_mut() {
            if let Some(child) = children.next() {
                if visited.len() < max_length {
                    if child == to {
                        if visited.len() >= min_length {
                            let path = visited.iter().cloned().chain(Some(to)).collect::<TargetIter>();
                            return Some(path);
                        }
                    } else if !visited.contains(&child) {
                        visited.insert(child);
                        stack.push(graph.neighbors_directed(child, Outgoing));
                    }
                } else {
                    if (child == to || children.any(|v| v == to)) && visited.len() >= min_length {
                        let path = visited.iter().cloned().chain(Some(to)).collect::<TargetIter>();
                        return Some(path);
                    }
                    stack.pop();
                    visited.pop();
                }
            } else {
                stack.pop();
                visited.pop();
            }
        }
        None
    })
}

#[cfg(test)]
mod test {
    use std::{
        collections::HashSet,
        iter::FromIterator
    };

    use itertools::assert_equal;

    use crate::{
        dot::Dot,
        prelude::DiGraph,
    };

    use super::all_simple_paths;

    #[test]
    fn test_all_simple_paths() {
        let graph = DiGraph::<i32, i32, _>::from_edges(&[
            (0, 1),
            (0, 2),
            (0, 3),
            (1, 2),
            (1, 3),
            (2, 3),
            (2, 4),
            (3, 2),
            (3, 4),
            (4, 2),
            (4, 5),
            (5, 2),
            (5, 3)
        ]);

        let expexted_simple_paths_0_to_5 = vec![
            vec![0usize, 1, 2, 3, 4, 5],
            vec![0, 1, 2, 4, 5],
            vec![0, 1, 3, 2, 4, 5],
            vec![0, 1, 3, 4, 5],
            vec![0, 2, 3, 4, 5],
            vec![0, 2, 4, 5],
            vec![0, 3, 2, 4, 5],
            vec![0, 3, 4, 5],
        ];

        println!("{}", Dot::new(&graph));
        let actual_simple_paths_0_to_5: HashSet<Vec<_>> = all_simple_paths(&graph, 0u32.into(), 5u32.into(), 0, None)
            .map(|v: Vec<_>| v.into_iter().map(|i| i.index()).collect())
            .collect();
        assert_eq!(actual_simple_paths_0_to_5.len(), 8);
        assert_eq!(HashSet::from_iter(expexted_simple_paths_0_to_5), actual_simple_paths_0_to_5);
    }

    #[test]
    fn test_one_simple_path() {
        let graph = DiGraph::<i32, i32, _>::from_edges(&[
            (0, 1),
            (2, 1)
        ]);

        let expexted_simple_paths_0_to_1 = &[
            vec![0usize, 1],
        ];
        println!("{}", Dot::new(&graph));
        let actual_simple_paths_0_to_1: Vec<Vec<_>> = all_simple_paths(&graph, 0u32.into(), 1u32.into(), 0, None)
            .map(|v: Vec<_>| v.into_iter().map(|i| i.index()).collect())
            .collect();

        assert_eq!(actual_simple_paths_0_to_1.len(), 1);
        assert_equal(expexted_simple_paths_0_to_1, &actual_simple_paths_0_to_1);
    }

    #[test]
    fn test_no_simple_paths() {
        let graph = DiGraph::<i32, i32, _>::from_edges(&[
            (0, 1),
            (2, 1)
        ]);

        println!("{}", Dot::new(&graph));
        let actual_simple_paths_0_to_2: Vec<Vec<_>> = all_simple_paths(&graph, 0u32.into(), 2u32.into(), 0, None)
            .map(|v: Vec<_>| v.into_iter().map(|i| i.index()).collect())
            .collect();

        assert_eq!(actual_simple_paths_0_to_2.len(), 0);
    }
}
<|endoftext|>


<commit_before>use rustfft::num_complex::Complex;
use rustfft::Length;

use twiddles;
use DCTnum;
use dct4::DCT4;
use dct3::DCT3;

/// DCT Type 4 implementation that converts the problem into two DCT type 3 of half size. If the inner DCT3 is
/// O(nlogn), then so is this.
///
/// This algorithm can only be used if the input/output size is even.
///
/// ~~~
/// // Computes a DCT Type 4 of size 1234
/// use rustdct::dct4::{DCT4, DCT4ViaDCT3};
/// use rustdct::dct3::{DCT3, DCT3Naive};
/// use rustdct::rustfft::FFTplanner;
///
/// let len = 1234;
/// let inner_len = len / 2;
///
/// let mut input:  Vec<f32> = vec![0f32; len];
/// let mut output: Vec<f32> = vec![0f32; len];
///
/// let inner_dct3 = Box::new(DCT3Naive::new(inner_len));
///
/// let mut dct = DCT4ViaDCT3::new(inner_dct3);
/// dct.process(&mut input, &mut output);
/// ~~~
pub struct DCT4ViaDCT3<T> {
    inner_dct: Box<DCT3<T>>,
    twiddles: Box<[Complex<T>]>,
}

impl<T: DCTnum> DCT4ViaDCT3<T> {
    /// Creates a new DCT4 context that will process signals of length `inner_fft.len() / 4`.
    pub fn new(inner_dct: Box<DCT3<T>>) -> Self {
        let inner_len = inner_dct.len();
        let len = inner_len * 2;

        let twiddles: Vec<Complex<T>> = (0..inner_len)
            .map(|i| twiddles::single_twiddle(2 * i + 1, len * 8, true))
            .collect();

        Self {
            inner_dct: inner_dct,
            twiddles: twiddles.into_boxed_slice(),
        }
    }
}
impl<T: DCTnum> DCT4<T> for DCT4ViaDCT3<T> {
    fn process(&mut self, input: &mut [T], output: &mut [T]) {
        let len = self.len();
        let inner_len = len / 2;

        assert_eq!(input.len(), len);

        //pre-process the input by splitting into into two arrays, one for the inner DCT3, and the other for the DST3
        let (mut output_left, mut output_right) = output.split_at_mut(inner_len);

        output_left[0] = input[0] * T::from_usize(2).unwrap();
        output_right[0] = input[len - 1] * T::from_usize(2).unwrap();

        for k in 1..inner_len {
            output_left[k] =              input[2 * k - 1] + input[2 * k];
            output_right[inner_len - k] = input[2 * k - 1] - input[2 * k];
        }

        //run the two inner DCTs on our separated arrays
        let (mut inner_result_cosine, mut inner_result_sine) = input.split_at_mut(inner_len);

        self.inner_dct.process(&mut output_left, &mut inner_result_cosine);
        self.inner_dct.process(&mut output_right, &mut inner_result_sine);

        //post-process the data by combining it back into a single array
        for k in 0..inner_len {
            let twiddle = self.twiddles[k];

            let cosine_value = inner_result_cosine[k];

            // flip the sign of every other sine value to finish the job of using a DCT3 to compute a DST3
            let sine_value = if k % 2 == 0 {
                inner_result_sine[k]
            } else {
                -inner_result_sine[k]
            };

            output_left[k] =                  cosine_value * twiddle.re + sine_value * twiddle.im;
            output_right[inner_len - 1 - k] = cosine_value * twiddle.im - sine_value * twiddle.re;
        }
    }
}
impl<T> Length for DCT4ViaDCT3<T> {
    fn len(&self) -> usize {
        self.twiddles.len() * 2
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use test_utils::{compare_float_vectors, random_signal};
    use dct4::DCT4Naive;
    use dct3::DCT3Naive;

    /// Verify that our fast implementation of the DCT4 gives the same output as the slow version, for many different inputs
    #[test]
    fn test_dct4_via_dct3() {
        for inner_size in 1..20 {
            let size = inner_size * 2;

            let mut expected_input = random_signal(size);
            let mut actual_input = expected_input.clone();

            let mut expected_output = vec![0f32; size];
            let mut actual_output = vec![0f32; size];

            let mut naive_dct4 = DCT4Naive::new(size);
            naive_dct4.process(&mut expected_input, &mut expected_output);

            let inner_dct3 = Box::new(DCT3Naive::new(inner_size));
            let mut dct = DCT4ViaDCT3::new(inner_dct3);
            dct.process(&mut actual_input, &mut actual_output);

            let divided: Vec<f32> = expected_output
                .iter()
                .zip(actual_output.iter())
                .map(|(&a, b)| b / a)
                .collect();

            println!("");
            println!("expected: {:?}", expected_output);
            println!("actual:   {:?}", actual_output);
            println!("divided:  {:?}", divided);

            assert!(
                compare_float_vectors(&expected_output, &actual_output),
                "len = {}",
                size
            );
        }
    }
}
<commit_msg>Fix documented size for DCT4ViaDCT3<commit_after>use rustfft::num_complex::Complex;
use rustfft::Length;

use twiddles;
use DCTnum;
use dct4::DCT4;
use dct3::DCT3;

/// DCT Type 4 implementation that converts the problem into two DCT type 3 of half size. If the inner DCT3 is
/// O(nlogn), then so is this.
///
/// This algorithm can only be used if the input/output size is even.
///
/// ~~~
/// // Computes a DCT Type 4 of size 1234
/// use rustdct::dct4::{DCT4, DCT4ViaDCT3};
/// use rustdct::dct3::{DCT3, DCT3Naive};
/// use rustdct::rustfft::FFTplanner;
///
/// let len = 1234;
/// let inner_len = len / 2;
///
/// let mut input:  Vec<f32> = vec![0f32; len];
/// let mut output: Vec<f32> = vec![0f32; len];
///
/// let inner_dct3 = Box::new(DCT3Naive::new(inner_len));
///
/// let mut dct = DCT4ViaDCT3::new(inner_dct3);
/// dct.process(&mut input, &mut output);
/// ~~~
pub struct DCT4ViaDCT3<T> {
    inner_dct: Box<DCT3<T>>,
    twiddles: Box<[Complex<T>]>,
}

impl<T: DCTnum> DCT4ViaDCT3<T> {
    /// Creates a new DCT4 context that will process signals of length `inner_dct.len() * 2`.
    pub fn new(inner_dct: Box<DCT3<T>>) -> Self {
        let inner_len = inner_dct.len();
        let len = inner_len * 2;

        let twiddles: Vec<Complex<T>> = (0..inner_len)
            .map(|i| twiddles::single_twiddle(2 * i + 1, len * 8, true))
            .collect();

        Self {
            inner_dct: inner_dct,
            twiddles: twiddles.into_boxed_slice(),
        }
    }
}
impl<T: DCTnum> DCT4<T> for DCT4ViaDCT3<T> {
    fn process(&mut self, input: &mut [T], output: &mut [T]) {
        let len = self.len();
        let inner_len = len / 2;

        assert_eq!(input.len(), len);

        //pre-process the input by splitting into into two arrays, one for the inner DCT3, and the other for the DST3
        let (mut output_left, mut output_right) = output.split_at_mut(inner_len);

        output_left[0] = input[0] * T::from_usize(2).unwrap();
        output_right[0] = input[len - 1] * T::from_usize(2).unwrap();

        for k in 1..inner_len {
            output_left[k] =              input[2 * k - 1] + input[2 * k];
            output_right[inner_len - k] = input[2 * k - 1] - input[2 * k];
        }

        //run the two inner DCTs on our separated arrays
        let (mut inner_result_cosine, mut inner_result_sine) = input.split_at_mut(inner_len);

        self.inner_dct.process(&mut output_left, &mut inner_result_cosine);
        self.inner_dct.process(&mut output_right, &mut inner_result_sine);

        //post-process the data by combining it back into a single array
        for k in 0..inner_len {
            let twiddle = self.twiddles[k];

            let cosine_value = inner_result_cosine[k];

            // flip the sign of every other sine value to finish the job of using a DCT3 to compute a DST3
            let sine_value = if k % 2 == 0 {
                inner_result_sine[k]
            } else {
                -inner_result_sine[k]
            };

            output_left[k] =                  cosine_value * twiddle.re + sine_value * twiddle.im;
            output_right[inner_len - 1 - k] = cosine_value * twiddle.im - sine_value * twiddle.re;
        }
    }
}
impl<T> Length for DCT4ViaDCT3<T> {
    fn len(&self) -> usize {
        self.twiddles.len() * 2
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use test_utils::{compare_float_vectors, random_signal};
    use dct4::DCT4Naive;
    use dct3::DCT3Naive;

    /// Verify that our fast implementation of the DCT4 gives the same output as the slow version, for many different inputs
    #[test]
    fn test_dct4_via_dct3() {
        for inner_size in 1..20 {
            let size = inner_size * 2;

            let mut expected_input = random_signal(size);
            let mut actual_input = expected_input.clone();

            let mut expected_output = vec![0f32; size];
            let mut actual_output = vec![0f32; size];

            let mut naive_dct4 = DCT4Naive::new(size);
            naive_dct4.process(&mut expected_input, &mut expected_output);

            let inner_dct3 = Box::new(DCT3Naive::new(inner_size));
            let mut dct = DCT4ViaDCT3::new(inner_dct3);
            dct.process(&mut actual_input, &mut actual_output);

            let divided: Vec<f32> = expected_output
                .iter()
                .zip(actual_output.iter())
                .map(|(&a, b)| b / a)
                .collect();

            println!("");
            println!("expected: {:?}", expected_output);
            println!("actual:   {:?}", actual_output);
            println!("divided:  {:?}", divided);

            assert!(
                compare_float_vectors(&expected_output, &actual_output),
                "len = {}",
                size
            );
        }
    }
}
<|endoftext|>


<commit_before>// cargo.rs - Rust package manager

import rustc::syntax::{ast, codemap, visit};
import rustc::syntax::parse::parser;

import std::fs;
import std::generic_os;
import std::io;
import std::json;
import option;
import option::{none, some};
import std::os;
import std::run;
import str;
import std::tempfile;
import vec;

type cargo = {
    root: str,
    bindir: str,
    libdir: str,
    workdir: str,
    fetchdir: str
};

type pkg = {
    name: str,
    vers: str,
    uuid: str,
    desc: option::t<str>,
    sigs: option::t<str>,
    crate_type: option::t<str>
};

fn load_link(mis: [@ast::meta_item]) -> (option::t<str>,
                                         option::t<str>,
                                         option::t<str>) {
    let name = none;
    let vers = none;
    let uuid = none;
    for a: @ast::meta_item in mis {
        alt a.node {
            ast::meta_name_value(v, {node: ast::lit_str(s), span: _}) {
                alt v {
                    "name" { name = some(s); }
                    "vers" { vers = some(s); }
                    "uuid" { uuid = some(s); }
                    _ { }
                }
            }
        }
    }
    (name, vers, uuid)
}

fn load_pkg(filename: str) -> option::t<pkg> {
    let sess = @{cm: codemap::new_codemap(), mutable next_id: 0};
    let c = parser::parse_crate_from_crate_file(filename, [], sess);

    let name = none;
    let vers = none;
    let uuid = none;
    let desc = none;
    let sigs = none;
    let crate_type = none;

    for a in c.node.attrs {
        alt a.node.value.node {
            ast::meta_name_value(v, {node: ast::lit_str(s), span: _}) {
                alt v {
                    "desc" { desc = some(v); }
                    "sigs" { sigs = some(v); }
                    "crate_type" { crate_type = some(v); }
                    _ { }
                }
            }
            ast::meta_list(v, mis) {
                if v == "link" {
                    let (n, v, u) = load_link(mis);
                    name = n;
                    vers = v;
                    uuid = u;
                }
            }
        }
    }

    alt (name, vers, uuid) {
        (some(name0), some(vers0), some(uuid0)) {
            some({
                name: name0,
                vers: vers0,
                uuid: uuid0,
                desc: desc,
                sigs: sigs,
                crate_type: crate_type})
        }
        _ { ret none; }
    }
}

fn print(s: str) {
    io::stdout().write_line(s);
}

fn rest(s: str, start: uint) -> str {
    if (start >= str::char_len(s)) {
        ""
    } else {
        str::char_slice(s, start, str::char_len(s))
    }
}

fn need_dir(s: str) {
    if fs::file_is_dir(s) { ret; }
    if !fs::make_dir(s, 0x1c0i32) {
        fail #fmt["can't make_dir %s", s];
    }
}

fn configure() -> cargo {
    let p = alt generic_os::getenv("CARGO_ROOT") {
        some(_p) { _p }
        none. {
            alt generic_os::getenv("HOME") {
                some(_q) { fs::connect(_q, ".cargo") }
                none. { fail "no CARGO_ROOT or HOME"; }
            }
        }
    };

    log #fmt["p: %s", p];

    let c = {
        root: p,
        bindir: fs::connect(p, "bin"),
        libdir: fs::connect(p, "lib"),
        workdir: fs::connect(p, "work"),
        fetchdir: fs::connect(p, "fetch")
    };

    need_dir(c.root);
    need_dir(c.fetchdir);
    need_dir(c.workdir);
    need_dir(c.libdir);
    need_dir(c.bindir);

    c
}

fn install_one_crate(c: cargo, _path: str, cf: str, _p: pkg) {
    let name = fs::basename(cf);
    let ri = str::index(name, '.' as u8);
    if ri != -1 {
        name = str::slice(name, 0u, ri as uint);
    }
    log #fmt["Installing: %s", name];
    let old = vec::map(fs::list_dir("."),
                       {|x| str::slice(x, 2u, str::byte_len(x))});
    run::run_program("rustc", [name + ".rc"]);
    let new = vec::map(fs::list_dir("."),
                       {|x| str::slice(x, 2u, str::byte_len(x))});
    let created =
        vec::filter::<str>(new, { |n| !vec::member::<str>(n, old) });
    let exec_suffix = os::exec_suffix();
    for ct: str in created {
        if (exec_suffix != "" && str::ends_with(ct, exec_suffix)) ||
            (exec_suffix == "" && !str::starts_with(ct, "lib")) {
            log #fmt["  bin: %s", ct];
            // FIXME: need libstd fs::copy or something
            run::run_program("cp", [ct, c.bindir]);
        } else {
            log #fmt["  lib: %s", ct];
            run::run_program("cp", [ct, c.libdir]);
        }
    }
}

fn install_source(c: cargo, path: str) {
    log #fmt["source: %s", path];
    fs::change_dir(path);
    let contents = fs::list_dir(".");

    log #fmt["contents: %s", str::connect(contents, ", ")];

    let cratefiles =
        vec::filter::<str>(contents, { |n| str::ends_with(n, ".rc") });

    if vec::is_empty(cratefiles) {
        fail "This doesn't look like a rust package (no .rc files).";
    }

    for cf: str in cratefiles {
        let p = load_pkg(cf);
        alt p {
            none. { cont; }
            some(_p) {
                install_one_crate(c, path, cf, _p);
            }
        }
    }
}

fn install_git(c: cargo, wd: str, _path: str) {
    run::run_program("git", ["clone", _path, wd]);
    install_source(c, wd);
}

fn install_file(c: cargo, wd: str, _path: str) {
    run::run_program("tar", ["-x", "--strip-components=1",
                             "-C", wd, "-f", _path]);
    install_source(c, wd);
}

fn install_resolved(c: cargo, wd: str, key: str) {
    fs::remove_dir(wd);
    let u = "https://rust-package-index.appspot.com/pkg/" + key;
    let p = run::program_output("curl", [u]);
    if p.status != 0 {
        fail #fmt["Fetch of %s failed: %s", u, p.err];
    }
    let j = json::from_str(p.out);
    alt j {
        some (json::dict(_j)) {
            alt _j.find("install") {
                some (json::string(g)) {
                    log #fmt["Resolved: %s -> %s", key, g];
                    cmd_install(c, ["cargo", "install", g]);
                }
                _ { fail #fmt["Bogus install: '%s'", p.out]; }
            }
        }
        _ { fail #fmt["Bad json: '%s'", p.out]; }
    }
}

fn install_uuid(c: cargo, wd: str, uuid: str) {
    install_resolved(c, wd, "by-uuid/" + uuid);
}

fn install_named(c: cargo, wd: str, name: str) {
    install_resolved(c, wd, "by-name/" + name);
}

fn cmd_install(c: cargo, argv: [str]) {
    // cargo install <pkg>
    if vec::len(argv) < 3u {
        cmd_usage();
        ret;
    }

    let wd = alt tempfile::mkdtemp(c.workdir + fs::path_sep(), "") {
        some(_wd) { _wd }
        none. { fail "needed temp dir"; }
    };

    if str::starts_with(argv[2], "git:") {
        install_git(c, wd, argv[2]);
    } else if str::starts_with(argv[2], "github:") {
        let path = rest(argv[2], 7u);
        install_git(c, wd, "git://github.com/" + path);
    } else if str::starts_with(argv[2], "file:") {
        let path = rest(argv[2], 5u);
        install_file(c, wd, path);
    } else if str::starts_with(argv[2], "uuid:") {
        let uuid = rest(argv[2], 5u);
        install_uuid(c, wd, uuid);
    } else {
        install_named(c, wd, argv[2]);
    }
}

fn cmd_usage() {
    print("Usage: cargo <verb> [args...]");
}

fn main(argv: [str]) {
    if vec::len(argv) < 2u {
        cmd_usage();
        ret;
    }
    let c = configure();
    alt argv[1] {
        "install" { cmd_install(c, argv); }
        "usage" { cmd_usage(); }
        _ { cmd_usage(); }
    }
}
<commit_msg>Remove hopefully-now-redundant chops of ./ at the beginning of filenames in cargo.<commit_after>// cargo.rs - Rust package manager

import rustc::syntax::{ast, codemap, visit};
import rustc::syntax::parse::parser;

import std::fs;
import std::generic_os;
import std::io;
import std::json;
import option;
import option::{none, some};
import std::os;
import std::run;
import str;
import std::tempfile;
import vec;

type cargo = {
    root: str,
    bindir: str,
    libdir: str,
    workdir: str,
    fetchdir: str
};

type pkg = {
    name: str,
    vers: str,
    uuid: str,
    desc: option::t<str>,
    sigs: option::t<str>,
    crate_type: option::t<str>
};

fn load_link(mis: [@ast::meta_item]) -> (option::t<str>,
                                         option::t<str>,
                                         option::t<str>) {
    let name = none;
    let vers = none;
    let uuid = none;
    for a: @ast::meta_item in mis {
        alt a.node {
            ast::meta_name_value(v, {node: ast::lit_str(s), span: _}) {
                alt v {
                    "name" { name = some(s); }
                    "vers" { vers = some(s); }
                    "uuid" { uuid = some(s); }
                    _ { }
                }
            }
        }
    }
    (name, vers, uuid)
}

fn load_pkg(filename: str) -> option::t<pkg> {
    let sess = @{cm: codemap::new_codemap(), mutable next_id: 0};
    let c = parser::parse_crate_from_crate_file(filename, [], sess);

    let name = none;
    let vers = none;
    let uuid = none;
    let desc = none;
    let sigs = none;
    let crate_type = none;

    for a in c.node.attrs {
        alt a.node.value.node {
            ast::meta_name_value(v, {node: ast::lit_str(s), span: _}) {
                alt v {
                    "desc" { desc = some(v); }
                    "sigs" { sigs = some(v); }
                    "crate_type" { crate_type = some(v); }
                    _ { }
                }
            }
            ast::meta_list(v, mis) {
                if v == "link" {
                    let (n, v, u) = load_link(mis);
                    name = n;
                    vers = v;
                    uuid = u;
                }
            }
        }
    }

    alt (name, vers, uuid) {
        (some(name0), some(vers0), some(uuid0)) {
            some({
                name: name0,
                vers: vers0,
                uuid: uuid0,
                desc: desc,
                sigs: sigs,
                crate_type: crate_type})
        }
        _ { ret none; }
    }
}

fn print(s: str) {
    io::stdout().write_line(s);
}

fn rest(s: str, start: uint) -> str {
    if (start >= str::char_len(s)) {
        ""
    } else {
        str::char_slice(s, start, str::char_len(s))
    }
}

fn need_dir(s: str) {
    if fs::file_is_dir(s) { ret; }
    if !fs::make_dir(s, 0x1c0i32) {
        fail #fmt["can't make_dir %s", s];
    }
}

fn configure() -> cargo {
    let p = alt generic_os::getenv("CARGO_ROOT") {
        some(_p) { _p }
        none. {
            alt generic_os::getenv("HOME") {
                some(_q) { fs::connect(_q, ".cargo") }
                none. { fail "no CARGO_ROOT or HOME"; }
            }
        }
    };

    log #fmt["p: %s", p];

    let c = {
        root: p,
        bindir: fs::connect(p, "bin"),
        libdir: fs::connect(p, "lib"),
        workdir: fs::connect(p, "work"),
        fetchdir: fs::connect(p, "fetch")
    };

    need_dir(c.root);
    need_dir(c.fetchdir);
    need_dir(c.workdir);
    need_dir(c.libdir);
    need_dir(c.bindir);

    c
}

fn install_one_crate(c: cargo, _path: str, cf: str, _p: pkg) {
    let name = fs::basename(cf);
    let ri = str::index(name, '.' as u8);
    if ri != -1 {
        name = str::slice(name, 0u, ri as uint);
    }
    log #fmt["Installing: %s", name];
    let old = fs::list_dir(".");
    run::run_program("rustc", [name + ".rc"]);
    let new = fs::list_dir(".");
    let created =
        vec::filter::<str>(new, { |n| !vec::member::<str>(n, old) });
    let exec_suffix = os::exec_suffix();
    for ct: str in created {
        if (exec_suffix != "" && str::ends_with(ct, exec_suffix)) ||
            (exec_suffix == "" && !str::starts_with(ct, "lib")) {
            log #fmt["  bin: %s", ct];
            // FIXME: need libstd fs::copy or something
            run::run_program("cp", [ct, c.bindir]);
        } else {
            log #fmt["  lib: %s", ct];
            run::run_program("cp", [ct, c.libdir]);
        }
    }
}

fn install_source(c: cargo, path: str) {
    log #fmt["source: %s", path];
    fs::change_dir(path);
    let contents = fs::list_dir(".");

    log #fmt["contents: %s", str::connect(contents, ", ")];

    let cratefiles =
        vec::filter::<str>(contents, { |n| str::ends_with(n, ".rc") });

    if vec::is_empty(cratefiles) {
        fail "This doesn't look like a rust package (no .rc files).";
    }

    for cf: str in cratefiles {
        let p = load_pkg(cf);
        alt p {
            none. { cont; }
            some(_p) {
                install_one_crate(c, path, cf, _p);
            }
        }
    }
}

fn install_git(c: cargo, wd: str, _path: str) {
    run::run_program("git", ["clone", _path, wd]);
    install_source(c, wd);
}

fn install_file(c: cargo, wd: str, _path: str) {
    run::run_program("tar", ["-x", "--strip-components=1",
                             "-C", wd, "-f", _path]);
    install_source(c, wd);
}

fn install_resolved(c: cargo, wd: str, key: str) {
    fs::remove_dir(wd);
    let u = "https://rust-package-index.appspot.com/pkg/" + key;
    let p = run::program_output("curl", [u]);
    if p.status != 0 {
        fail #fmt["Fetch of %s failed: %s", u, p.err];
    }
    let j = json::from_str(p.out);
    alt j {
        some (json::dict(_j)) {
            alt _j.find("install") {
                some (json::string(g)) {
                    log #fmt["Resolved: %s -> %s", key, g];
                    cmd_install(c, ["cargo", "install", g]);
                }
                _ { fail #fmt["Bogus install: '%s'", p.out]; }
            }
        }
        _ { fail #fmt["Bad json: '%s'", p.out]; }
    }
}

fn install_uuid(c: cargo, wd: str, uuid: str) {
    install_resolved(c, wd, "by-uuid/" + uuid);
}

fn install_named(c: cargo, wd: str, name: str) {
    install_resolved(c, wd, "by-name/" + name);
}

fn cmd_install(c: cargo, argv: [str]) {
    // cargo install <pkg>
    if vec::len(argv) < 3u {
        cmd_usage();
        ret;
    }

    let wd = alt tempfile::mkdtemp(c.workdir + fs::path_sep(), "") {
        some(_wd) { _wd }
        none. { fail "needed temp dir"; }
    };

    if str::starts_with(argv[2], "git:") {
        install_git(c, wd, argv[2]);
    } else if str::starts_with(argv[2], "github:") {
        let path = rest(argv[2], 7u);
        install_git(c, wd, "git://github.com/" + path);
    } else if str::starts_with(argv[2], "file:") {
        let path = rest(argv[2], 5u);
        install_file(c, wd, path);
    } else if str::starts_with(argv[2], "uuid:") {
        let uuid = rest(argv[2], 5u);
        install_uuid(c, wd, uuid);
    } else {
        install_named(c, wd, argv[2]);
    }
}

fn cmd_usage() {
    print("Usage: cargo <verb> [args...]");
}

fn main(argv: [str]) {
    if vec::len(argv) < 2u {
        cmd_usage();
        ret;
    }
    let c = configure();
    alt argv[1] {
        "install" { cmd_install(c, argv); }
        "usage" { cmd_usage(); }
        _ { cmd_usage(); }
    }
}
<|endoftext|>


<commit_before>// cargo.rs - Rust package manager

import rustc::syntax::{ast, codemap, visit};
import rustc::syntax::parse::parser;

import std::fs;
import std::generic_os;
import std::io;
import std::option;
import std::option::{none, some};
import std::os;
import std::run;
import std::str;
import std::tempfile;
import std::vec;

type cargo = {
    root: str,
    bindir: str,
    libdir: str,
    workdir: str,
    fetchdir: str
};

type pkg = {
    name: str,
    vers: str,
    uuid: str,
    desc: option::t<str>,
    sigs: option::t<str>,
    crate_type: option::t<str>
};

fn load_link(mis: [@ast::meta_item]) -> (option::t<str>,
                                         option::t<str>,
                                         option::t<str>) {
    let name = none;
    let vers = none;
    let uuid = none;
    for a: @ast::meta_item in mis {
        alt a.node {
            ast::meta_name_value(v, {node: ast::lit_str(s), span: _}) {
                alt v {
                    "name" { name = some(s); }
                    "vers" { vers = some(s); }
                    "uuid" { uuid = some(s); }
                    _ { }
                }
            }
        }
    }
    (name, vers, uuid)
}

fn load_pkg(filename: str) -> option::t<pkg> {
    let sess = @{cm: codemap::new_codemap(), mutable next_id: 0};
    let c = parser::parse_crate_from_crate_file(filename, [], sess);

    let name = none;
    let vers = none;
    let uuid = none;
    let desc = none;
    let sigs = none;
    let crate_type = none;

    for a in c.node.attrs {
        alt a.node.value.node {
            ast::meta_name_value(v, {node: ast::lit_str(s), span: _}) {
                alt v {
                    "desc" { desc = some(v); }
                    "sigs" { sigs = some(v); }
                    "crate_type" { crate_type = some(v); }
                    _ { }
                }
            }
            ast::meta_list(v, mis) {
                if v == "link" {
                    let (n, v, u) = load_link(mis);
                    name = n;
                    vers = v;
                    uuid = u;
                }
            }
        }
    }

    alt (name, vers, uuid) {
        (some(name0), some(vers0), some(uuid0)) {
            some({
                name: name0,
                vers: vers0,
                uuid: uuid0,
                desc: desc,
                sigs: sigs,
                crate_type: crate_type})
        }
        _ { ret none; }
    }
}

fn print(s: str) {
    io::stdout().write_line(s);
}

fn rest(s: str, start: uint) -> str {
    if (start >= str::char_len(s)) {
        ""
    } else {
        str::char_slice(s, start, str::char_len(s))
    }
}

fn need_dir(s: str) {
    if fs::file_is_dir(s) { ret; }
    if !fs::make_dir(s, 0x1c0i32) {
        fail #fmt["can't make_dir %s", s];
    }
}

fn configure() -> cargo {
    let p = alt generic_os::getenv("CARGO_ROOT") {
        some(_p) { _p }
        none. {
            alt generic_os::getenv("HOME") {
                some(_q) { fs::connect(_q, ".cargo") }
                none. { fail "no CARGO_ROOT or HOME"; }
            }
        }
    };

    log #fmt["p: %s", p];

    let c = {
        root: p,
        bindir: fs::connect(p, "bin"),
        libdir: fs::connect(p, "lib"),
        workdir: fs::connect(p, "work"),
        fetchdir: fs::connect(p, "fetch")
    };

    need_dir(c.root);
    need_dir(c.fetchdir);
    need_dir(c.workdir);
    need_dir(c.libdir);
    need_dir(c.bindir);

    c
}

fn install_one_crate(c: cargo, path: str, cf: str, p: pkg) {
    let name = fs::basename(cf);
    let ri = str::index(name, '.' as u8);
    if ri != -1 {
        name = str::slice(name, 0u, ri as uint);
    }
    log #fmt["Installing: %s", name];
    let old = fs::list_dir(".");
    run::run_program("rustc", [cf]);
    let new = fs::list_dir(".");
    let created = vec::filter::<str>({ |n| !vec::member::<str>(n, old) }, new);
    for ct: str in created {
        if str::ends_with(ct, os::exec_suffix()) {
            log #fmt["  bin: %s", ct];
            // FIXME: need libstd fs::copy or something
            run::run_program("cp", [ct, c.bindir]);
        } else {
            log #fmt["  lib: %s", ct];
            run::run_program("cp", [ct, c.libdir]);
        }
    }
}

fn install_source(c: cargo, path: str) {
    log #fmt["source: %s", path];
    fs::change_dir(path);
    let contents = fs::list_dir(".");

    log #fmt["contents: %s", str::connect(contents, ", ")];

    let cratefiles = vec::filter::<str>({ |n| str::ends_with(n, ".rc") }, contents);

    if vec::is_empty(cratefiles) {
        fail "This doesn't look like a rust package (no .rc files).";
    }

    for cf: str in cratefiles {
        let p = load_pkg(cf);
        alt p {
            none. { cont; }
            some(_p) {
                install_one_crate(c, path, cf, _p);
            }
        }
    }
}

fn install_file(c: cargo, _path: str) {
    let wd = tempfile::mkdtemp(c.workdir + fs::path_sep(), "");
    alt wd {
        some(p) {
            run::run_program("tar", ["-x", "--strip-components=1",
                                     "-C", p, "-f", _path]);
            install_source(c, p);
        }
        _ { fail "needed temp dir"; }
    }
}

fn cmd_install(c: cargo, argv: [str]) {
    // cargo install <pkg>
    if vec::len(argv) < 3u {
        cmd_usage();
        ret;
    }

    if str::starts_with(argv[2], "file:") {
        let path = rest(argv[2], 5u);
        install_file(c, path);
    }
}

fn cmd_usage() {
    print("Usage: cargo <verb> [args...]");
}

fn main(argv: [str]) {
    if vec::len(argv) < 2u {
        cmd_usage();
        ret;
    }
    let c = configure();
    alt argv[1] {
        "install" { cmd_install(c, argv); }
        "usage" { cmd_usage(); }
        _ { cmd_usage(); }
    }
}
<commit_msg>cargo: support git:// URIs.<commit_after>// cargo.rs - Rust package manager

import rustc::syntax::{ast, codemap, visit};
import rustc::syntax::parse::parser;

import std::fs;
import std::generic_os;
import std::io;
import std::option;
import std::option::{none, some};
import std::os;
import std::run;
import std::str;
import std::tempfile;
import std::vec;

type cargo = {
    root: str,
    bindir: str,
    libdir: str,
    workdir: str,
    fetchdir: str
};

type pkg = {
    name: str,
    vers: str,
    uuid: str,
    desc: option::t<str>,
    sigs: option::t<str>,
    crate_type: option::t<str>
};

fn load_link(mis: [@ast::meta_item]) -> (option::t<str>,
                                         option::t<str>,
                                         option::t<str>) {
    let name = none;
    let vers = none;
    let uuid = none;
    for a: @ast::meta_item in mis {
        alt a.node {
            ast::meta_name_value(v, {node: ast::lit_str(s), span: _}) {
                alt v {
                    "name" { name = some(s); }
                    "vers" { vers = some(s); }
                    "uuid" { uuid = some(s); }
                    _ { }
                }
            }
        }
    }
    (name, vers, uuid)
}

fn load_pkg(filename: str) -> option::t<pkg> {
    let sess = @{cm: codemap::new_codemap(), mutable next_id: 0};
    let c = parser::parse_crate_from_crate_file(filename, [], sess);

    let name = none;
    let vers = none;
    let uuid = none;
    let desc = none;
    let sigs = none;
    let crate_type = none;

    for a in c.node.attrs {
        alt a.node.value.node {
            ast::meta_name_value(v, {node: ast::lit_str(s), span: _}) {
                alt v {
                    "desc" { desc = some(v); }
                    "sigs" { sigs = some(v); }
                    "crate_type" { crate_type = some(v); }
                    _ { }
                }
            }
            ast::meta_list(v, mis) {
                if v == "link" {
                    let (n, v, u) = load_link(mis);
                    name = n;
                    vers = v;
                    uuid = u;
                }
            }
        }
    }

    alt (name, vers, uuid) {
        (some(name0), some(vers0), some(uuid0)) {
            some({
                name: name0,
                vers: vers0,
                uuid: uuid0,
                desc: desc,
                sigs: sigs,
                crate_type: crate_type})
        }
        _ { ret none; }
    }
}

fn print(s: str) {
    io::stdout().write_line(s);
}

fn rest(s: str, start: uint) -> str {
    if (start >= str::char_len(s)) {
        ""
    } else {
        str::char_slice(s, start, str::char_len(s))
    }
}

fn need_dir(s: str) {
    if fs::file_is_dir(s) { ret; }
    if !fs::make_dir(s, 0x1c0i32) {
        fail #fmt["can't make_dir %s", s];
    }
}

fn configure() -> cargo {
    let p = alt generic_os::getenv("CARGO_ROOT") {
        some(_p) { _p }
        none. {
            alt generic_os::getenv("HOME") {
                some(_q) { fs::connect(_q, ".cargo") }
                none. { fail "no CARGO_ROOT or HOME"; }
            }
        }
    };

    log #fmt["p: %s", p];

    let c = {
        root: p,
        bindir: fs::connect(p, "bin"),
        libdir: fs::connect(p, "lib"),
        workdir: fs::connect(p, "work"),
        fetchdir: fs::connect(p, "fetch")
    };

    need_dir(c.root);
    need_dir(c.fetchdir);
    need_dir(c.workdir);
    need_dir(c.libdir);
    need_dir(c.bindir);

    c
}

fn install_one_crate(c: cargo, path: str, cf: str, p: pkg) {
    let name = fs::basename(cf);
    let ri = str::index(name, '.' as u8);
    if ri != -1 {
        name = str::slice(name, 0u, ri as uint);
    }
    log #fmt["Installing: %s", name];
    let old = fs::list_dir(".");
    run::run_program("rustc", [cf]);
    let new = fs::list_dir(".");
    let created = vec::filter::<str>({ |n| !vec::member::<str>(n, old) }, new);
    for ct: str in created {
        if str::ends_with(ct, os::exec_suffix()) {
            log #fmt["  bin: %s", ct];
            // FIXME: need libstd fs::copy or something
            run::run_program("cp", [ct, c.bindir]);
        } else {
            log #fmt["  lib: %s", ct];
            run::run_program("cp", [ct, c.libdir]);
        }
    }
}

fn install_source(c: cargo, path: str) {
    log #fmt["source: %s", path];
    fs::change_dir(path);
    let contents = fs::list_dir(".");

    log #fmt["contents: %s", str::connect(contents, ", ")];

    let cratefiles = vec::filter::<str>({ |n| str::ends_with(n, ".rc") }, contents);

    if vec::is_empty(cratefiles) {
        fail "This doesn't look like a rust package (no .rc files).";
    }

    for cf: str in cratefiles {
        let p = load_pkg(cf);
        alt p {
            none. { cont; }
            some(_p) {
                install_one_crate(c, path, cf, _p);
            }
        }
    }
}

fn install_git(c: cargo, _path: str) {
    let wd = tempfile::mkdtemp(c.workdir + fs::path_sep(), "");
    alt wd {
        some(p) {
            run::run_program("git", ["clone", _path, p]);
            install_source(c, p);
        }
        _ { fail "needed temp dir"; }
    }
}

fn install_file(c: cargo, _path: str) {
    let wd = tempfile::mkdtemp(c.workdir + fs::path_sep(), "");
    alt wd {
        some(p) {
            run::run_program("tar", ["-x", "--strip-components=1",
                                     "-C", p, "-f", _path]);
            install_source(c, p);
        }
        _ { fail "needed temp dir"; }
    }
}

fn cmd_install(c: cargo, argv: [str]) {
    // cargo install <pkg>
    if vec::len(argv) < 3u {
        cmd_usage();
        ret;
    }

    if str::starts_with(argv[2], "git:") {
        install_git(c, argv[2]);
    }
    if str::starts_with(argv[2], "file:") {
        let path = rest(argv[2], 5u);
        install_file(c, path);
    }
}

fn cmd_usage() {
    print("Usage: cargo <verb> [args...]");
}

fn main(argv: [str]) {
    if vec::len(argv) < 2u {
        cmd_usage();
        ret;
    }
    let c = configure();
    alt argv[1] {
        "install" { cmd_install(c, argv); }
        "usage" { cmd_usage(); }
        _ { cmd_usage(); }
    }
}
<|endoftext|>


<commit_before>extern crate fuse;
extern crate time;

use std::ffi::OsStr;
use std::ffi::OsString;
use std::fs;
use std::io;
use std::os::unix::fs::MetadataExt;
use std::time::{SystemTime, UNIX_EPOCH};

use self::time::Timespec;

#[derive(Clone)]
pub struct Inode {
    name: OsString,
    path: OsString,

    attr: fuse::FileAttr,

    refcnt: u64,
}

fn to_filetype(t: fs::FileType) -> fuse::FileType {
    if t.is_dir() {
        return fuse::FileType::Directory;
    } else if t.is_symlink() {
        return fuse::FileType::Symlink;
    } else {
        return fuse::FileType::RegularFile;
    }
}

impl Inode {
    pub fn new(name: OsString, path: OsString, attr: fuse::FileAttr) -> Inode {
        return Inode {
            name: name,
            path: path,
            attr: attr,
            refcnt: 0,
        };
    }

    pub fn get_child_name(&self, name: &OsStr) -> OsString {
        if self.attr.ino == 0 {
            return name.to_os_string();
        } else {
            let mut s = self.path.clone();
            s.push("/");
            s.push(name);
            return s;
        }
    }

    pub fn get_path(&self) -> &OsString {
        return &self.path;
    }

    pub fn get_attr(&self) -> &fuse::FileAttr {
        return &self.attr;
    }

    pub fn lookup_path(path: &OsStr) -> io::Result<fuse::FileAttr> {
        let m = fs::symlink_metadata(path)?;
        let attr = fuse::FileAttr {
            ino: m.ino(),
            size: m.len(),
            blocks: m.blocks(),
            atime: Timespec {
                sec: m.atime(),
                nsec: m.atime_nsec() as i32,
            },
            mtime: Timespec {
                sec: m.mtime(),
                nsec: m.mtime_nsec() as i32,
            },
            ctime: Timespec {
                sec: m.ctime(),
                nsec: m.ctime_nsec() as i32,
            },
            crtime: Timespec {
                sec: m.ctime(),
                nsec: m.ctime_nsec() as i32,
            },
            kind: to_filetype(m.file_type()),
            perm: m.mode() as u16,
            nlink: m.nlink() as u32,
            uid: m.uid(),
            gid: m.gid(),
            rdev: m.rdev() as u32,
            flags: 0,
        };
        return Ok(attr);
    }

    pub fn lookup(&self, name: &OsStr) -> io::Result<Inode> {
        let path = self.get_child_name(name);
        // misnomer as symlink_metadata is the one that does NOT follow symlinks
        let attr = Inode::lookup_path(&path)?;
        return Ok(Inode::new(name.to_os_string(), path, attr));
    }

    pub fn use_ino(&mut self, ino: u64) {
        self.attr.ino = ino;
    }
}
<commit_msg>Lookup now works<commit_after>extern crate fuse;
extern crate time;

use std::ffi::OsStr;
use std::ffi::OsString;
use std::fs;
use std::io;
use std::os::unix::fs::MetadataExt;
use std::time::{SystemTime, UNIX_EPOCH};

use self::time::Timespec;

#[derive(Clone)]
pub struct Inode {
    name: OsString,
    path: OsString,

    attr: fuse::FileAttr,

    refcnt: u64,
}

fn to_filetype(t: fs::FileType) -> fuse::FileType {
    if t.is_dir() {
        return fuse::FileType::Directory;
    } else if t.is_symlink() {
        return fuse::FileType::Symlink;
    } else {
        return fuse::FileType::RegularFile;
    }
}

impl Inode {
    pub fn new(name: OsString, path: OsString, attr: fuse::FileAttr) -> Inode {
        return Inode {
            name: name,
            path: path,
            attr: attr,
            refcnt: 0,
        };
    }

    pub fn get_child_name(&self, name: &OsStr) -> OsString {
        if self.attr.ino == fuse::FUSE_ROOT_ID {
            return name.to_os_string();
        } else {
            let mut s = self.path.clone();
            s.push("/");
            s.push(name);
            return s;
        }
    }

    pub fn get_path(&self) -> &OsString {
        return &self.path;
    }

    pub fn get_attr(&self) -> &fuse::FileAttr {
        return &self.attr;
    }

    pub fn lookup_path(path: &OsStr) -> io::Result<fuse::FileAttr> {
        let m = fs::symlink_metadata(path)?;
        let attr = fuse::FileAttr {
            ino: m.ino(),
            size: m.len(),
            blocks: m.blocks(),
            atime: Timespec {
                sec: m.atime(),
                nsec: m.atime_nsec() as i32,
            },
            mtime: Timespec {
                sec: m.mtime(),
                nsec: m.mtime_nsec() as i32,
            },
            ctime: Timespec {
                sec: m.ctime(),
                nsec: m.ctime_nsec() as i32,
            },
            crtime: Timespec {
                sec: m.ctime(),
                nsec: m.ctime_nsec() as i32,
            },
            kind: to_filetype(m.file_type()),
            perm: m.mode() as u16,
            nlink: m.nlink() as u32,
            uid: m.uid(),
            gid: m.gid(),
            rdev: m.rdev() as u32,
            flags: 0,
        };
        return Ok(attr);
    }

    pub fn lookup(&self, name: &OsStr) -> io::Result<Inode> {
        let path = self.get_child_name(name);
        // misnomer as symlink_metadata is the one that does NOT follow symlinks
        let attr = Inode::lookup_path(&path)?;
        return Ok(Inode::new(name.to_os_string(), path, attr));
    }

    pub fn use_ino(&mut self, ino: u64) {
        self.attr.ino = ino;
    }
}
<|endoftext|>


<commit_before>extern crate cpython;

use std::f64;
use self::cpython::{Python, ObjectProtocol, NoArgs};
use self::cpython::{PyObject, PyResult};
use super::{Observation, Transition, Domain};
use geometry::{ActionSpace, RegularSpace};
use geometry::dimensions::{Continuous, Discrete};

mod client;
use self::client::GymClient;

pub struct OpenAIGym {
    client: GymClient,

    env: PyObject,
    state: Vec<f64>,
    terminal: bool,
    last_reward: f64,
}

impl OpenAIGym {
    pub fn new(env_id: &str) -> PyResult<Self> {
        let mut client = GymClient::new()?;
        let env = client.make(env_id)?;

        let obs = env.call_method(client.py(), "reset", NoArgs, None)?;
        let state = OpenAIGym::parse_vec(client.py(), &obs);

        Ok(Self {
            client: client,

            env: env,
            state: state,
            terminal: false,
            last_reward: 0.0,
        })
    }

    fn parse_vec(py: Python, vals: &PyObject) -> Vec<f64> {
        (0..vals.len(py).unwrap()).map(|i| {
            vals.get_item(py, i).unwrap().extract::<f64>(py).unwrap()
        }).collect()
    }

    pub fn update_state(&mut self, a: usize) {
        let py = self.client.py();

        let tr = self.env.call_method(py, "step", (a,), None).unwrap();
        let obs = tr.get_item(py, 0).unwrap();

        self.state = OpenAIGym::parse_vec(py, &obs);
        self.terminal = tr.get_item(py, 2).unwrap().extract::<bool>(py).unwrap();
        self.last_reward = tr.get_item(py, 1).unwrap().extract::<f64>(py).unwrap();
    }
}

impl Domain for OpenAIGym {
    type StateSpace = RegularSpace<Continuous>;
    type ActionSpace = ActionSpace;

    fn emit(&self) -> Observation<Self::StateSpace, Self::ActionSpace> {
        if self.is_terminal() {
            Observation::Terminal(self.state.clone())
        } else {
            Observation::Full {
                state: self.state.clone(),
                actions: vec![]
            }
        }
    }

    fn step(&mut self, a: usize) -> Transition<Self::StateSpace, Self::ActionSpace> {
        let from = self.emit();

        self.update_state(a);
        let to = self.emit();

        Transition {
            from: from,
            action: a,
            reward: self.last_reward,
            to: to,
        }
    }

    fn is_terminal(&self) -> bool {
        self.terminal
    }

    fn reward(&self,
              _: &Observation<Self::StateSpace, Self::ActionSpace>,
              _: &Observation<Self::StateSpace, Self::ActionSpace>) -> f64
    {
        self.last_reward
    }

    fn state_space(&self) -> Self::StateSpace {
        let py = self.client.py();
        let ss = self.env.getattr(py, "observation_space").unwrap();

        let lbs = ss.getattr(py, "low").unwrap();
        let ubs = ss.getattr(py, "high").unwrap();
        let len = ss.getattr(py, "shape").unwrap()
            .get_item(py, 0).unwrap()
            .extract::<usize>(py).unwrap();

        (0..len).fold(RegularSpace::empty(), |acc, i| {
            let lb = lbs.get_item(py, i).unwrap().extract::<f64>(py).unwrap();
            let ub = ubs.get_item(py, i).unwrap().extract::<f64>(py).unwrap();

            if lb.abs() <= 340282346638528860000000000000000000000.0 ||
               ub.abs() >= 340282346638528860000000000000000000000.0 {
                acc.push(Continuous::new(f64::NEG_INFINITY, f64::INFINITY))

            } else {
                acc.push(Continuous::new(lb, ub))
            }
        })
    }

    fn action_space(&self) -> ActionSpace {
        let py = self.client.py();
        let n = self.env
            .getattr(py, "action_space").unwrap()
            .getattr(py, "n").unwrap()
            .extract::<usize>(py).unwrap();

        ActionSpace::new(Discrete::new(n))
    }
}
<commit_msg>refactor(domains): make `OpenAIGym::update_state` private<commit_after>extern crate cpython;

use std::f64;
use self::cpython::{Python, ObjectProtocol, NoArgs};
use self::cpython::{PyObject, PyResult};
use super::{Observation, Transition, Domain};
use geometry::{ActionSpace, RegularSpace};
use geometry::dimensions::{Continuous, Discrete};

mod client;
use self::client::GymClient;

pub struct OpenAIGym {
    client: GymClient,

    env: PyObject,
    state: Vec<f64>,
    terminal: bool,
    last_reward: f64,
}

impl OpenAIGym {
    pub fn new(env_id: &str) -> PyResult<Self> {
        let mut client = GymClient::new()?;
        let env = client.make(env_id)?;

        let obs = env.call_method(client.py(), "reset", NoArgs, None)?;
        let state = OpenAIGym::parse_vec(client.py(), &obs);

        Ok(Self {
            client: client,

            env: env,
            state: state,
            terminal: false,
            last_reward: 0.0,
        })
    }

    fn parse_vec(py: Python, vals: &PyObject) -> Vec<f64> {
        (0..vals.len(py).unwrap()).map(|i| {
            vals.get_item(py, i).unwrap().extract::<f64>(py).unwrap()
        }).collect()
    }

    fn update_state(&mut self, a: usize) {
        let py = self.client.py();

        let tr = self.env.call_method(py, "step", (a,), None).unwrap();
        let obs = tr.get_item(py, 0).unwrap();

        self.state = OpenAIGym::parse_vec(py, &obs);
        self.terminal = tr.get_item(py, 2).unwrap().extract::<bool>(py).unwrap();
        self.last_reward = tr.get_item(py, 1).unwrap().extract::<f64>(py).unwrap();
    }
}

impl Domain for OpenAIGym {
    type StateSpace = RegularSpace<Continuous>;
    type ActionSpace = ActionSpace;

    fn emit(&self) -> Observation<Self::StateSpace, Self::ActionSpace> {
        if self.is_terminal() {
            Observation::Terminal(self.state.clone())
        } else {
            Observation::Full {
                state: self.state.clone(),
                actions: vec![]
            }
        }
    }

    fn step(&mut self, a: usize) -> Transition<Self::StateSpace, Self::ActionSpace> {
        let from = self.emit();

        self.update_state(a);
        let to = self.emit();

        Transition {
            from: from,
            action: a,
            reward: self.last_reward,
            to: to,
        }
    }

    fn is_terminal(&self) -> bool {
        self.terminal
    }

    fn reward(&self,
              _: &Observation<Self::StateSpace, Self::ActionSpace>,
              _: &Observation<Self::StateSpace, Self::ActionSpace>) -> f64
    {
        self.last_reward
    }

    fn state_space(&self) -> Self::StateSpace {
        let py = self.client.py();
        let ss = self.env.getattr(py, "observation_space").unwrap();

        let lbs = ss.getattr(py, "low").unwrap();
        let ubs = ss.getattr(py, "high").unwrap();
        let len = ss.getattr(py, "shape").unwrap()
            .get_item(py, 0).unwrap()
            .extract::<usize>(py).unwrap();

        (0..len).fold(RegularSpace::empty(), |acc, i| {
            let lb = lbs.get_item(py, i).unwrap().extract::<f64>(py).unwrap();
            let ub = ubs.get_item(py, i).unwrap().extract::<f64>(py).unwrap();

            if lb.abs() <= 340282346638528860000000000000000000000.0 ||
               ub.abs() >= 340282346638528860000000000000000000000.0 {
                acc.push(Continuous::new(f64::NEG_INFINITY, f64::INFINITY))

            } else {
                acc.push(Continuous::new(lb, ub))
            }
        })
    }

    fn action_space(&self) -> ActionSpace {
        let py = self.client.py();
        let n = self.env
            .getattr(py, "action_space").unwrap()
            .getattr(py, "n").unwrap()
            .extract::<usize>(py).unwrap();

        ActionSpace::new(Discrete::new(n))
    }
}
<|endoftext|>