<commit_before>use regex::Regex;
use std::fs::File;
use std::io::{self, BufRead};
use std::str::FromStr;

#[macro_use]
extern crate lazy_static;

struct State<T>(Box<dyn Iterator<Item = T>>, Option<T>);
pub struct Merge {
    count: usize,
    states: Vec<State<u32>>,
}

impl Merge {
    pub fn new(filename: &str) -> Self {
        let count = get_number(filename).unwrap();
        let states = (0..count).map(|i| {
            let collection = Box::new(get_collection(filename, i).unwrap());
            State(collection, None)
        }).collect();
        Merge {
            count: count,
            states: states,
        }
    }
}

impl Iterator for Merge {
    type Item = u32;
    fn next(&mut self) -> Option<Self::Item> {
        let count = self.count;
        let states = &mut self.states;
        loop {
            for i in 0..count {
                let state = &mut states[i];
                if state.1.is_none() {
                    state.1 = state.0.next();
                }
            }
            let not_done = states.iter().any(|s| s.1.is_some());
            if !not_done {
                return None;
            }

            let (mut min, mut min_index) = (u32::MAX, usize::MIN);
            for i in 0..count {
                if let Some(val) = states[i].1 {
                    if val < min {
                        min = val;
                        min_index = i;
                    }
                }
            }
            states[min_index].1 = None;
            return Some(min);
        }
    }
}

pub fn get_number(filename: &str) -> io::Result<usize> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"NUMBER=(\d+)").unwrap();
    }
    let mut matches = match_lines(filename, &*RE)?;
    return Ok(matches.next().unwrap().parse().unwrap());
}

pub fn get_output<T: FromStr>(filename: &str) -> io::Result<impl Iterator<Item = T>> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"OUTPUT:(.*)").unwrap();
    }
    get_numbers(filename, &*RE)
}

pub fn get_collection<T: FromStr>(filename: &str, idx: usize) -> io::Result<impl Iterator<Item = T>> {
    let regex: Regex = {
        let r = format!("COLLECTION{}:(.*)", idx);
        Regex::new(&r).unwrap()
    };
    get_numbers(filename, &regex)
}

fn get_numbers<T: FromStr>(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = T>> {
    let matches = match_lines(filename, regex)?;
    let to_int = |v: &str| -> Option<T> {
        if let Ok(i) = v.parse::<T>() {
            Some(i)
        } else {
            None
        }
    };
    let values = matches
        .map(move |s| {
            let numbers = s.split(',').filter_map(|v| to_int(&v));
            numbers.collect::<Vec<_>>()
        })
        .flatten();
    Ok(values)
}

fn match_lines(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = String>> {
    let read_lines = move || -> io::Result<_> {
        let file = File::open(filename)?;
        Ok(io::BufReader::new(file).lines().map(|line| line.unwrap()))
    };
    let lines = read_lines()?;
    let r = regex.clone(); // TODO
    let matches =
        lines.filter_map(move |line| r.captures(&line).map(|captures| captures[1].to_string()));
    Ok(matches)
}

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

    #[test]
    fn test_number() {
        assert_eq!(get_number("../data/test.txt").unwrap(), 3);
    }

    #[test]
    fn test_output() {
        let output = [1, 1, 2, 2, 3, 4, 4, 6, 7, 9, 9, 20, 21];
        assert_eq!(
            get_output("../data/test.txt").unwrap().collect::<Vec<u32>>(),
            output
        );
    }

    #[test]
    fn test_collection() {
        let output = [2, 4, 6, 9, 20];
        assert_eq!(
            get_collection("../data/test.txt", 1)
                .unwrap()
                .collect::<Vec<u32>>(),
            output
        );
    }

    fn merge(filename: &str) -> (impl Iterator<Item = u32>, impl Iterator<Item = u32>) {
        let result = Merge::new(filename);
        let output = get_output(filename).unwrap();
        (result, output)
    }

    fn assert_iterator(
        iter1: &mut impl Iterator<Item = u32>,
        iter2: &mut impl Iterator<Item = u32>,
    ) -> bool {
        loop {
            match (iter1.next(), iter2.next()) {
                (None, None) => return true,
                (Some(v1), Some(v2)) if v1 == v2 => continue,
                _ => return false,
            }
        }
    }

    #[test]
    fn test_merge() {
        let filename = "../data/test.txt";
        let (mut result, mut output) = merge(filename);
        assert!(assert_iterator(&mut result, &mut output));
    }

    #[test]
    #[should_panic]
    fn test_bad_merge() {
        let filename = "../data/bad.txt";
        let (_result, _output) = merge(filename);
    }

    #[test]
    fn test_zero_merge() {
        let filename = "../data/zero.txt";
        let (mut result, mut output) = merge(filename);
        assert!(result.next().is_none());
        assert!(output.next().is_none());
    }

    #[test]
    fn test_err() {
        let filename = "../data/err.txt";
        let (mut result, mut output) = merge(filename);
        assert!(!assert_iterator(&mut result, &mut output));
    }
}
<commit_msg>use generics<commit_after>use regex::Regex;
use std::fs::File;
use std::io::{self, BufRead};
use std::str::FromStr;

#[macro_use]
extern crate lazy_static;

struct State<T>(Box<dyn Iterator<Item = T>>, Option<T>);
pub struct Merge<T> {
    max: T, // TODO
    count: usize,
    states: Vec<State<T>>,
}

impl<T: 'static + FromStr> Merge<T> {
    pub fn new(filename: &str, max: T) -> Self {
        let count = get_number(filename).unwrap();
        let states = (0..count).map(|i| {
            let collection = Box::new(get_collection(filename, i).unwrap());
            State(collection, None)
        }).collect();
        Merge {
            count: count,
            states: states,
            max: max,
        }
    }
}

impl<T: 'static + PartialOrd + Copy> Iterator for Merge<T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        let count = self.count;
        let max = self.max;
        let states = &mut self.states;
        loop {
            for i in 0..count {
                let state = &mut states[i];
                if state.1.is_none() {
                    state.1 = state.0.next();
                }
            }
            let not_done = states.iter().any(|s| s.1.is_some());
            if !not_done {
                return None;
            }

            let (mut min, mut min_index) = (max, usize::MIN);
            for i in 0..count {
                if let Some(val) = states[i].1 {
                    if val < min {
                        min = val;
                        min_index = i;
                    }
                }
            }
            states[min_index].1 = None;
            return Some(min);
        }
    }
}

pub fn get_number(filename: &str) -> io::Result<usize> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"NUMBER=(\d+)").unwrap();
    }
    let mut matches = match_lines(filename, &*RE)?;
    return Ok(matches.next().unwrap().parse().unwrap());
}

pub fn get_output<T: FromStr>(filename: &str) -> io::Result<impl Iterator<Item = T>> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"OUTPUT:(.*)").unwrap();
    }
    get_numbers(filename, &*RE)
}

pub fn get_collection<T: FromStr>(filename: &str, idx: usize) -> io::Result<impl Iterator<Item = T>> {
    let regex: Regex = {
        let r = format!("COLLECTION{}:(.*)", idx);
        Regex::new(&r).unwrap()
    };
    get_numbers(filename, &regex)
}

fn get_numbers<T: FromStr>(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = T>> {
    let matches = match_lines(filename, regex)?;
    let to_int = |v: &str| -> Option<T> {
        if let Ok(i) = v.parse::<T>() {
            Some(i)
        } else {
            None
        }
    };
    let values = matches
        .map(move |s| {
            let numbers = s.split(',').filter_map(|v| to_int(&v));
            numbers.collect::<Vec<_>>()
        })
        .flatten();
    Ok(values)
}

fn match_lines(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = String>> {
    let read_lines = move || -> io::Result<_> {
        let file = File::open(filename)?;
        Ok(io::BufReader::new(file).lines().map(|line| line.unwrap()))
    };
    let lines = read_lines()?;
    let r = regex.clone(); // TODO
    let matches =
        lines.filter_map(move |line| r.captures(&line).map(|captures| captures[1].to_string()));
    Ok(matches)
}

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

    #[test]
    fn test_number() {
        assert_eq!(get_number("../data/test.txt").unwrap(), 3);
    }

    #[test]
    fn test_output() {
        let output = [1, 1, 2, 2, 3, 4, 4, 6, 7, 9, 9, 20, 21];
        assert_eq!(
            get_output("../data/test.txt").unwrap().collect::<Vec<u32>>(),
            output
        );
    }

    #[test]
    fn test_collection() {
        let output = [2, 4, 6, 9, 20];
        assert_eq!(
            get_collection("../data/test.txt", 1)
                .unwrap()
                .collect::<Vec<u32>>(),
            output
        );
    }

    fn merge(filename: &str) -> (impl Iterator<Item = u32>, impl Iterator<Item = u32>) {
        let result = Merge::new(filename, u32::MAX);
        let output = get_output(filename).unwrap();
        (result, output)
    }

    fn assert_iterator(
        iter1: &mut impl Iterator<Item = u32>,
        iter2: &mut impl Iterator<Item = u32>,
    ) -> bool {
        loop {
            match (iter1.next(), iter2.next()) {
                (None, None) => return true,
                (Some(v1), Some(v2)) if v1 == v2 => continue,
                _ => return false,
            }
        }
    }

    #[test]
    fn test_merge() {
        let filename = "../data/test.txt";
        let (mut result, mut output) = merge(filename);
        assert!(assert_iterator(&mut result, &mut output));
    }

    #[test]
    #[should_panic]
    fn test_bad_merge() {
        let filename = "../data/bad.txt";
        let (_result, _output) = merge(filename);
    }

    #[test]
    fn test_zero_merge() {
        let filename = "../data/zero.txt";
        let (mut result, mut output) = merge(filename);
        assert!(result.next().is_none());
        assert!(output.next().is_none());
    }

    #[test]
    fn test_err() {
        let filename = "../data/err.txt";
        let (mut result, mut output) = merge(filename);
        assert!(!assert_iterator(&mut result, &mut output));
    }
}
<|endoftext|>


<commit_before><commit_msg>Store client and server proposals, check AEAD or lack of integrity<commit_after><|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 core::prelude::*;

use driver::session;
use metadata::cstore;
use metadata::filesearch;

use core::hashmap::HashSet;
use core::os;
use core::uint;
use core::util;
use core::vec;

fn not_win32(os: session::os) -> bool {
  match os {
      session::os_win32 => false,
      _ => true
  }
}

pub fn get_rpath_flags(sess: session::Session, out_filename: &Path)
                    -> ~[~str] {
    let os = sess.targ_cfg.os;

    // No rpath on windows
    if os == session::os_win32 {
        return ~[];
    }

    debug!("preparing the RPATH!");

    let sysroot = sess.filesearch.sysroot();
    let output = out_filename;
    let libs = cstore::get_used_crate_files(sess.cstore);
    // We don't currently rpath extern libraries, but we know
    // where rustrt is and we know every rust program needs it
    let libs = vec::append_one(libs, get_sysroot_absolute_rt_lib(sess));

    let rpaths = get_rpaths(os, sysroot, output, libs,
                            sess.opts.target_triple);
    rpaths_to_flags(rpaths)
}

fn get_sysroot_absolute_rt_lib(sess: session::Session) -> Path {
    let r = filesearch::relative_target_lib_path(sess.opts.target_triple);
    sess.filesearch.sysroot().push_rel(&r).push(os::dll_filename("rustrt"))
}

pub fn rpaths_to_flags(rpaths: &[Path]) -> ~[~str] {
    vec::map(rpaths, |rpath| fmt!("-Wl,-rpath,%s",rpath.to_str()))
}

fn get_rpaths(os: session::os,
              sysroot: &Path,
              output: &Path,
              libs: &[Path],
              target_triple: &str) -> ~[Path] {
    debug!("sysroot: %s", sysroot.to_str());
    debug!("output: %s", output.to_str());
    debug!("libs:");
    for libs.each |libpath| {
        debug!("    %s", libpath.to_str());
    }
    debug!("target_triple: %s", target_triple);

    // Use relative paths to the libraries. Binaries can be moved
    // as long as they maintain the relative relationship to the
    // crates they depend on.
    let rel_rpaths = get_rpaths_relative_to_output(os, output, libs);

    // And a final backup rpath to the global library location.
    let fallback_rpaths = ~[get_install_prefix_rpath(target_triple)];

    fn log_rpaths(desc: &str, rpaths: &[Path]) {
        debug!("%s rpaths:", desc);
        for rpaths.each |rpath| {
            debug!("    %s", rpath.to_str());
        }
    }

    log_rpaths("relative", rel_rpaths);
    log_rpaths("fallback", fallback_rpaths);

    let mut rpaths = rel_rpaths;
    rpaths.push_all(fallback_rpaths);

    // Remove duplicates
    let rpaths = minimize_rpaths(rpaths);
    return rpaths;
}

fn get_rpaths_relative_to_output(os: session::os,
                                 output: &Path,
                                 libs: &[Path]) -> ~[Path] {
    vec::map(libs, |a| {
        get_rpath_relative_to_output(os, output, a)
    })
}

pub fn get_rpath_relative_to_output(os: session::os,
                                    output: &Path,
                                    lib: &Path)
                                 -> Path {
    use core::os;

    assert!(not_win32(os));

    // Mac doesn't appear to support $ORIGIN
    let prefix = match os {
        session::os_android |session::os_linux | session::os_freebsd
                          => "$ORIGIN",
        session::os_macos => "@executable_path",
        session::os_win32 => util::unreachable()
    };

    Path(prefix).push_rel(&get_relative_to(&os::make_absolute(output),
                                           &os::make_absolute(lib)))
}

// Find the relative path from one file to another
pub fn get_relative_to(abs1: &Path, abs2: &Path) -> Path {
    assert!(abs1.is_absolute);
    assert!(abs2.is_absolute);
    let abs1 = abs1.normalize();
    let abs2 = abs2.normalize();
    debug!("finding relative path from %s to %s",
           abs1.to_str(), abs2.to_str());
    let split1: &[~str] = abs1.components;
    let split2: &[~str] = abs2.components;
    let len1 = split1.len();
    let len2 = split2.len();
    assert!(len1 > 0);
    assert!(len2 > 0);

    let max_common_path = uint::min(len1, len2) - 1;
    let mut start_idx = 0;
    while start_idx < max_common_path
        && split1[start_idx] == split2[start_idx] {
        start_idx += 1;
    }

    let mut path = ~[];
    for uint::range(start_idx, len1 - 1) |_i| { path.push(~".."); };

    path.push_all(vec::slice(split2, start_idx, len2 - 1));

    if !path.is_empty() {
        return Path("").push_many(path);
    } else {
        return Path(".");
    }
}

#[cfg(stage0)]
pub fn get_install_prefix_rpath(target_triple: &str) -> Path {
    let install_prefix = env!("CFG_PREFIX");

    if install_prefix.is_empty() {
        fail!("rustc compiled without CFG_PREFIX environment variable");
    }

    let tlib = filesearch::relative_target_lib_path(target_triple);
    os::make_absolute(&Path(install_prefix).push_rel(&tlib))
}

#[cfg(not(stage0))]
pub fn get_install_prefix_rpath(target_triple: &str) -> Path {
    let install_prefix = env!("CFG_PREFIX");

    if install_prefix == "" {
        fail!("rustc compiled without CFG_PREFIX environment variable");
    }

    let tlib = filesearch::relative_target_lib_path(target_triple);
    os::make_absolute(&Path(install_prefix).push_rel(&tlib))
}

pub fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] {
    let mut set = HashSet::new();
    let mut minimized = ~[];
    for rpaths.each |rpath| {
        if set.insert(rpath.to_str()) {
            minimized.push(copy *rpath);
        }
    }
    minimized
}

#[cfg(unix, test)]
mod test {
    use core::prelude::*;

    // FIXME(#2119): the outer attribute should be #[cfg(unix, test)], then
    // these redundant #[cfg(test)] blocks can be removed
    #[cfg(test)]
    #[cfg(test)]
    use back::rpath::{get_install_prefix_rpath};
    use back::rpath::{get_relative_to, get_rpath_relative_to_output};
    use back::rpath::{minimize_rpaths, rpaths_to_flags};
    use driver::session;

    #[test]
    fn test_rpaths_to_flags() {
        let flags = rpaths_to_flags([Path("path1"),
                                     Path("path2")]);
        assert_eq!(flags, ~[~"-Wl,-rpath,path1", ~"-Wl,-rpath,path2"]);
    }

    #[test]
    fn test_prefix_rpath() {
        let res = get_install_prefix_rpath("triple");
        let d = Path(env!("CFG_PREFIX"))
            .push_rel(&Path("lib/rustc/triple/lib"));
        debug!("test_prefix_path: %s vs. %s",
               res.to_str(),
               d.to_str());
        assert!(res.to_str().ends_with(d.to_str()));
    }

    #[test]
    fn test_prefix_rpath_abs() {
        let res = get_install_prefix_rpath("triple");
        assert!(res.is_absolute);
    }

    #[test]
    fn test_minimize1() {
        let res = minimize_rpaths([Path("rpath1"),
                                   Path("rpath2"),
                                   Path("rpath1")]);
        assert_eq!(res, ~[Path("rpath1"), Path("rpath2")]);
    }

    #[test]
    fn test_minimize2() {
        let res = minimize_rpaths([Path("1a"), Path("2"), Path("2"),
                                   Path("1a"), Path("4a"),Path("1a"),
                                   Path("2"), Path("3"), Path("4a"),
                                   Path("3")]);
        assert_eq!(res, ~[Path("1a"), Path("2"), Path("4a"), Path("3")]);
    }

    #[test]
    fn test_relative_to1() {
        let p1 = Path("/usr/bin/rustc");
        let p2 = Path("/usr/lib/mylib");
        let res = get_relative_to(&p1, &p2);
        assert_eq!(res, Path("../lib"));
    }

    #[test]
    fn test_relative_to2() {
        let p1 = Path("/usr/bin/rustc");
        let p2 = Path("/usr/bin/../lib/mylib");
        let res = get_relative_to(&p1, &p2);
        assert_eq!(res, Path("../lib"));
    }

    #[test]
    fn test_relative_to3() {
        let p1 = Path("/usr/bin/whatever/rustc");
        let p2 = Path("/usr/lib/whatever/mylib");
        let res = get_relative_to(&p1, &p2);
        assert_eq!(res, Path("../../lib/whatever"));
    }

    #[test]
    fn test_relative_to4() {
        let p1 = Path("/usr/bin/whatever/../rustc");
        let p2 = Path("/usr/lib/whatever/mylib");
        let res = get_relative_to(&p1, &p2);
        assert_eq!(res, Path("../lib/whatever"));
    }

    #[test]
    fn test_relative_to5() {
        let p1 = Path("/usr/bin/whatever/../rustc");
        let p2 = Path("/usr/lib/whatever/../mylib");
        let res = get_relative_to(&p1, &p2);
        assert_eq!(res, Path("../lib"));
    }

    #[test]
    fn test_relative_to6() {
        let p1 = Path("/1");
        let p2 = Path("/2/3");
        let res = get_relative_to(&p1, &p2);
        assert_eq!(res, Path("2"));
    }

    #[test]
    fn test_relative_to7() {
        let p1 = Path("/1/2");
        let p2 = Path("/3");
        let res = get_relative_to(&p1, &p2);
        assert_eq!(res, Path(".."));
    }

    #[test]
    fn test_relative_to8() {
        let p1 = Path("/home/brian/Dev/rust/build/").push_rel(
            &Path("stage2/lib/rustc/i686-unknown-linux-gnu/lib/librustc.so"));
        let p2 = Path("/home/brian/Dev/rust/build/stage2/bin/..").push_rel(
            &Path("lib/rustc/i686-unknown-linux-gnu/lib/libstd.so"));
        let res = get_relative_to(&p1, &p2);
        debug!("test_relative_tu8: %s vs. %s",
               res.to_str(),
               Path(".").to_str());
        assert_eq!(res, Path("."));
    }

    #[test]
    #[cfg(target_os = "linux")]
    #[cfg(target_os = "andorid")]
    fn test_rpath_relative() {
      let o = session::os_linux;
      let res = get_rpath_relative_to_output(o,
            &Path("bin/rustc"), &Path("lib/libstd.so"));
      assert_eq!(res.to_str(), ~"$ORIGIN/../lib");
    }

    #[test]
    #[cfg(target_os = "freebsd")]
    fn test_rpath_relative() {
        let o = session::os_freebsd;
        let res = get_rpath_relative_to_output(o,
            &Path("bin/rustc"), &Path("lib/libstd.so"));
        assert_eq!(res.to_str(), ~"$ORIGIN/../lib");
    }

    #[test]
    #[cfg(target_os = "macos")]
    fn test_rpath_relative() {
        // this is why refinements would be nice
        let o = session::os_macos;
        let res = get_rpath_relative_to_output(o,
                                               &Path("bin/rustc"),
                                               &Path("lib/libstd.so"));
        assert_eq!(res.to_str(), ~"@executable_path/../lib");
    }
}
<commit_msg>Revert "stop using an absolute rpath"<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 core::prelude::*;

use driver::session;
use metadata::cstore;
use metadata::filesearch;

use core::hashmap::HashSet;
use core::os;
use core::uint;
use core::util;
use core::vec;

fn not_win32(os: session::os) -> bool {
  match os {
      session::os_win32 => false,
      _ => true
  }
}

pub fn get_rpath_flags(sess: session::Session, out_filename: &Path)
                    -> ~[~str] {
    let os = sess.targ_cfg.os;

    // No rpath on windows
    if os == session::os_win32 {
        return ~[];
    }

    debug!("preparing the RPATH!");

    let sysroot = sess.filesearch.sysroot();
    let output = out_filename;
    let libs = cstore::get_used_crate_files(sess.cstore);
    // We don't currently rpath extern libraries, but we know
    // where rustrt is and we know every rust program needs it
    let libs = vec::append_one(libs, get_sysroot_absolute_rt_lib(sess));

    let rpaths = get_rpaths(os, sysroot, output, libs,
                            sess.opts.target_triple);
    rpaths_to_flags(rpaths)
}

fn get_sysroot_absolute_rt_lib(sess: session::Session) -> Path {
    let r = filesearch::relative_target_lib_path(sess.opts.target_triple);
    sess.filesearch.sysroot().push_rel(&r).push(os::dll_filename("rustrt"))
}

pub fn rpaths_to_flags(rpaths: &[Path]) -> ~[~str] {
    vec::map(rpaths, |rpath| fmt!("-Wl,-rpath,%s",rpath.to_str()))
}

fn get_rpaths(os: session::os,
              sysroot: &Path,
              output: &Path,
              libs: &[Path],
              target_triple: &str) -> ~[Path] {
    debug!("sysroot: %s", sysroot.to_str());
    debug!("output: %s", output.to_str());
    debug!("libs:");
    for libs.each |libpath| {
        debug!("    %s", libpath.to_str());
    }
    debug!("target_triple: %s", target_triple);

    // Use relative paths to the libraries. Binaries can be moved
    // as long as they maintain the relative relationship to the
    // crates they depend on.
    let rel_rpaths = get_rpaths_relative_to_output(os, output, libs);

    // Make backup absolute paths to the libraries. Binaries can
    // be moved as long as the crates they link against don't move.
    let abs_rpaths = get_absolute_rpaths(libs);

    // And a final backup rpath to the global library location.
    let fallback_rpaths = ~[get_install_prefix_rpath(target_triple)];

    fn log_rpaths(desc: &str, rpaths: &[Path]) {
        debug!("%s rpaths:", desc);
        for rpaths.each |rpath| {
            debug!("    %s", rpath.to_str());
        }
    }

    log_rpaths("relative", rel_rpaths);
    log_rpaths("absolute", abs_rpaths);
    log_rpaths("fallback", fallback_rpaths);

    let mut rpaths = rel_rpaths;
    rpaths.push_all(abs_rpaths);
    rpaths.push_all(fallback_rpaths);

    // Remove duplicates
    let rpaths = minimize_rpaths(rpaths);
    return rpaths;
}

fn get_rpaths_relative_to_output(os: session::os,
                                 output: &Path,
                                 libs: &[Path]) -> ~[Path] {
    vec::map(libs, |a| {
        get_rpath_relative_to_output(os, output, a)
    })
}

pub fn get_rpath_relative_to_output(os: session::os,
                                    output: &Path,
                                    lib: &Path)
                                 -> Path {
    use core::os;

    assert!(not_win32(os));

    // Mac doesn't appear to support $ORIGIN
    let prefix = match os {
        session::os_android |session::os_linux | session::os_freebsd
                          => "$ORIGIN",
        session::os_macos => "@executable_path",
        session::os_win32 => util::unreachable()
    };

    Path(prefix).push_rel(&get_relative_to(&os::make_absolute(output),
                                           &os::make_absolute(lib)))
}

// Find the relative path from one file to another
pub fn get_relative_to(abs1: &Path, abs2: &Path) -> Path {
    assert!(abs1.is_absolute);
    assert!(abs2.is_absolute);
    let abs1 = abs1.normalize();
    let abs2 = abs2.normalize();
    debug!("finding relative path from %s to %s",
           abs1.to_str(), abs2.to_str());
    let split1: &[~str] = abs1.components;
    let split2: &[~str] = abs2.components;
    let len1 = split1.len();
    let len2 = split2.len();
    assert!(len1 > 0);
    assert!(len2 > 0);

    let max_common_path = uint::min(len1, len2) - 1;
    let mut start_idx = 0;
    while start_idx < max_common_path
        && split1[start_idx] == split2[start_idx] {
        start_idx += 1;
    }

    let mut path = ~[];
    for uint::range(start_idx, len1 - 1) |_i| { path.push(~".."); };

    path.push_all(vec::slice(split2, start_idx, len2 - 1));

    if !path.is_empty() {
        return Path("").push_many(path);
    } else {
        return Path(".");
    }
}

fn get_absolute_rpaths(libs: &[Path]) -> ~[Path] {
    vec::map(libs, |a| get_absolute_rpath(a) )
}

pub fn get_absolute_rpath(lib: &Path) -> Path {
    os::make_absolute(lib).dir_path()
}

#[cfg(stage0)]
pub fn get_install_prefix_rpath(target_triple: &str) -> Path {
    let install_prefix = env!("CFG_PREFIX");

    if install_prefix.is_empty() {
        fail!("rustc compiled without CFG_PREFIX environment variable");
    }

    let tlib = filesearch::relative_target_lib_path(target_triple);
    os::make_absolute(&Path(install_prefix).push_rel(&tlib))
}

#[cfg(not(stage0))]
pub fn get_install_prefix_rpath(target_triple: &str) -> Path {
    let install_prefix = env!("CFG_PREFIX");

    if install_prefix == "" {
        fail!("rustc compiled without CFG_PREFIX environment variable");
    }

    let tlib = filesearch::relative_target_lib_path(target_triple);
    os::make_absolute(&Path(install_prefix).push_rel(&tlib))
}

pub fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] {
    let mut set = HashSet::new();
    let mut minimized = ~[];
    for rpaths.each |rpath| {
        if set.insert(rpath.to_str()) {
            minimized.push(copy *rpath);
        }
    }
    minimized
}

#[cfg(unix, test)]
mod test {
    use core::prelude::*;
    use core::os;

    // FIXME(#2119): the outer attribute should be #[cfg(unix, test)], then
    // these redundant #[cfg(test)] blocks can be removed
    #[cfg(test)]
    #[cfg(test)]
    use back::rpath::{get_absolute_rpath, get_install_prefix_rpath};
    use back::rpath::{get_relative_to, get_rpath_relative_to_output};
    use back::rpath::{minimize_rpaths, rpaths_to_flags};
    use driver::session;

    #[test]
    fn test_rpaths_to_flags() {
        let flags = rpaths_to_flags([Path("path1"),
                                     Path("path2")]);
        assert_eq!(flags, ~[~"-Wl,-rpath,path1", ~"-Wl,-rpath,path2"]);
    }

    #[test]
    fn test_prefix_rpath() {
        let res = get_install_prefix_rpath("triple");
        let d = Path(env!("CFG_PREFIX"))
            .push_rel(&Path("lib/rustc/triple/lib"));
        debug!("test_prefix_path: %s vs. %s",
               res.to_str(),
               d.to_str());
        assert!(res.to_str().ends_with(d.to_str()));
    }

    #[test]
    fn test_prefix_rpath_abs() {
        let res = get_install_prefix_rpath("triple");
        assert!(res.is_absolute);
    }

    #[test]
    fn test_minimize1() {
        let res = minimize_rpaths([Path("rpath1"),
                                   Path("rpath2"),
                                   Path("rpath1")]);
        assert_eq!(res, ~[Path("rpath1"), Path("rpath2")]);
    }

    #[test]
    fn test_minimize2() {
        let res = minimize_rpaths([Path("1a"), Path("2"), Path("2"),
                                   Path("1a"), Path("4a"),Path("1a"),
                                   Path("2"), Path("3"), Path("4a"),
                                   Path("3")]);
        assert_eq!(res, ~[Path("1a"), Path("2"), Path("4a"), Path("3")]);
    }

    #[test]
    fn test_relative_to1() {
        let p1 = Path("/usr/bin/rustc");
        let p2 = Path("/usr/lib/mylib");
        let res = get_relative_to(&p1, &p2);
        assert_eq!(res, Path("../lib"));
    }

    #[test]
    fn test_relative_to2() {
        let p1 = Path("/usr/bin/rustc");
        let p2 = Path("/usr/bin/../lib/mylib");
        let res = get_relative_to(&p1, &p2);
        assert_eq!(res, Path("../lib"));
    }

    #[test]
    fn test_relative_to3() {
        let p1 = Path("/usr/bin/whatever/rustc");
        let p2 = Path("/usr/lib/whatever/mylib");
        let res = get_relative_to(&p1, &p2);
        assert_eq!(res, Path("../../lib/whatever"));
    }

    #[test]
    fn test_relative_to4() {
        let p1 = Path("/usr/bin/whatever/../rustc");
        let p2 = Path("/usr/lib/whatever/mylib");
        let res = get_relative_to(&p1, &p2);
        assert_eq!(res, Path("../lib/whatever"));
    }

    #[test]
    fn test_relative_to5() {
        let p1 = Path("/usr/bin/whatever/../rustc");
        let p2 = Path("/usr/lib/whatever/../mylib");
        let res = get_relative_to(&p1, &p2);
        assert_eq!(res, Path("../lib"));
    }

    #[test]
    fn test_relative_to6() {
        let p1 = Path("/1");
        let p2 = Path("/2/3");
        let res = get_relative_to(&p1, &p2);
        assert_eq!(res, Path("2"));
    }

    #[test]
    fn test_relative_to7() {
        let p1 = Path("/1/2");
        let p2 = Path("/3");
        let res = get_relative_to(&p1, &p2);
        assert_eq!(res, Path(".."));
    }

    #[test]
    fn test_relative_to8() {
        let p1 = Path("/home/brian/Dev/rust/build/").push_rel(
            &Path("stage2/lib/rustc/i686-unknown-linux-gnu/lib/librustc.so"));
        let p2 = Path("/home/brian/Dev/rust/build/stage2/bin/..").push_rel(
            &Path("lib/rustc/i686-unknown-linux-gnu/lib/libstd.so"));
        let res = get_relative_to(&p1, &p2);
        debug!("test_relative_tu8: %s vs. %s",
               res.to_str(),
               Path(".").to_str());
        assert_eq!(res, Path("."));
    }

    #[test]
    #[cfg(target_os = "linux")]
    #[cfg(target_os = "andorid")]
    fn test_rpath_relative() {
      let o = session::os_linux;
      let res = get_rpath_relative_to_output(o,
            &Path("bin/rustc"), &Path("lib/libstd.so"));
      assert_eq!(res.to_str(), ~"$ORIGIN/../lib");
    }

    #[test]
    #[cfg(target_os = "freebsd")]
    fn test_rpath_relative() {
        let o = session::os_freebsd;
        let res = get_rpath_relative_to_output(o,
            &Path("bin/rustc"), &Path("lib/libstd.so"));
        assert_eq!(res.to_str(), ~"$ORIGIN/../lib");
    }

    #[test]
    #[cfg(target_os = "macos")]
    fn test_rpath_relative() {
        // this is why refinements would be nice
        let o = session::os_macos;
        let res = get_rpath_relative_to_output(o,
                                               &Path("bin/rustc"),
                                               &Path("lib/libstd.so"));
        assert_eq!(res.to_str(), ~"@executable_path/../lib");
    }

    #[test]
    fn test_get_absolute_rpath() {
        let res = get_absolute_rpath(&Path("lib/libstd.so"));
        debug!("test_get_absolute_rpath: %s vs. %s",
               res.to_str(),
               os::make_absolute(&Path("lib")).to_str());

        assert_eq!(res, os::make_absolute(&Path("lib")));
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 rustc::mir::repr::*;
use rustc::middle::ty;
use std::io::{self, Write};

const INDENT: &'static str = "    ";

/// Write out a human-readable textual representation for the given MIR.
pub fn write_mir_pretty<W: Write>(mir: &Mir, w: &mut W) -> io::Result<()> {
    try!(write_mir_intro(mir, w));

    // Nodes
    for block in mir.all_basic_blocks() {
        try!(write_basic_block(block, mir, w));
    }

    writeln!(w, "}}")
}

/// Write out a human-readable textual representation for the given basic block.
fn write_basic_block<W: Write>(block: BasicBlock, mir: &Mir, w: &mut W) -> io::Result<()> {
    let data = mir.basic_block_data(block);

    // Basic block label at the top.
    try!(writeln!(w, "\n{}{:?}: {{", INDENT, block));

    // List of statements in the middle.
    for statement in &data.statements {
        try!(writeln!(w, "{0}{0}{1:?};", INDENT, statement));
    }

    // Terminator at the bottom.
    try!(writeln!(w, "{0}{0}{1:?};", INDENT, data.terminator));

    writeln!(w, "{}}}", INDENT)
}

/// Write out a human-readable textual representation of the MIR's `fn` type and the types of its
/// local variables (both user-defined bindings and compiler temporaries).
fn write_mir_intro<W: Write>(mir: &Mir, w: &mut W) -> io::Result<()> {
    try!(write!(w, "fn("));

    // fn argument types.
    for (i, arg) in mir.arg_decls.iter().enumerate() {
        if i > 0 {
            try!(write!(w, ", "));
        }
        try!(write!(w, "{:?}: {}", Lvalue::Arg(i as u32), arg.ty));
    }

    try!(write!(w, ") -> "));

    // fn return type.
    match mir.return_ty {
        ty::FnOutput::FnConverging(ty) => try!(write!(w, "{}", ty)),
        ty::FnOutput::FnDiverging => try!(write!(w, "!")),
    }

    try!(writeln!(w, " {{"));

    // User variable types (including the user's name in a comment).
    for (i, var) in mir.var_decls.iter().enumerate() {
        try!(write!(w, "{}let ", INDENT));
        if var.mutability == Mutability::Mut {
            try!(write!(w, "mut "));
        }
        try!(writeln!(w, "{:?}: {}; // {}", Lvalue::Var(i as u32), var.ty, var.name));
    }

    // Compiler-introduced temporary types.
    for (i, temp) in mir.temp_decls.iter().enumerate() {
        try!(writeln!(w, "{}let mut {:?}: {};", INDENT, Lvalue::Temp(i as u32), temp.ty));
    }

    Ok(())
}
<commit_msg>Rollup merge of #30771 - tsion:mir-text-terminator-fix, r=eddyb<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 rustc::mir::repr::*;
use rustc::middle::ty;
use std::io::{self, Write};

const INDENT: &'static str = "    ";

/// Write out a human-readable textual representation for the given MIR.
pub fn write_mir_pretty<W: Write>(mir: &Mir, w: &mut W) -> io::Result<()> {
    try!(write_mir_intro(mir, w));

    // Nodes
    for block in mir.all_basic_blocks() {
        try!(write_basic_block(block, mir, w));
    }

    writeln!(w, "}}")
}

/// Write out a human-readable textual representation for the given basic block.
fn write_basic_block<W: Write>(block: BasicBlock, mir: &Mir, w: &mut W) -> io::Result<()> {
    let data = mir.basic_block_data(block);

    // Basic block label at the top.
    try!(writeln!(w, "\n{}{:?}: {{", INDENT, block));

    // List of statements in the middle.
    for statement in &data.statements {
        try!(writeln!(w, "{0}{0}{1:?};", INDENT, statement));
    }

    // Terminator at the bottom.
    try!(writeln!(w, "{0}{0}{1:?};", INDENT, data.terminator()));

    writeln!(w, "{}}}", INDENT)
}

/// Write out a human-readable textual representation of the MIR's `fn` type and the types of its
/// local variables (both user-defined bindings and compiler temporaries).
fn write_mir_intro<W: Write>(mir: &Mir, w: &mut W) -> io::Result<()> {
    try!(write!(w, "fn("));

    // fn argument types.
    for (i, arg) in mir.arg_decls.iter().enumerate() {
        if i > 0 {
            try!(write!(w, ", "));
        }
        try!(write!(w, "{:?}: {}", Lvalue::Arg(i as u32), arg.ty));
    }

    try!(write!(w, ") -> "));

    // fn return type.
    match mir.return_ty {
        ty::FnOutput::FnConverging(ty) => try!(write!(w, "{}", ty)),
        ty::FnOutput::FnDiverging => try!(write!(w, "!")),
    }

    try!(writeln!(w, " {{"));

    // User variable types (including the user's name in a comment).
    for (i, var) in mir.var_decls.iter().enumerate() {
        try!(write!(w, "{}let ", INDENT));
        if var.mutability == Mutability::Mut {
            try!(write!(w, "mut "));
        }
        try!(writeln!(w, "{:?}: {}; // {}", Lvalue::Var(i as u32), var.ty, var.name));
    }

    // Compiler-introduced temporary types.
    for (i, temp) in mir.temp_decls.iter().enumerate() {
        try!(writeln!(w, "{}let mut {:?}: {};", INDENT, Lvalue::Temp(i as u32), temp.ty));
    }

    Ok(())
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 std::default::Default;
use std::fs::File;
use std::io::prelude::*;
use std::io;
use std::path::{PathBuf, Path};

use getopts;
use testing;
use rustc::session::search_paths::SearchPaths;
use rustc::session::config::Externs;
use syntax::codemap::DUMMY_SP;

use externalfiles::{ExternalHtml, LoadStringError, load_string};

use html::render::reset_ids;
use html::escape::Escape;
use html::markdown;
use html::markdown::{Markdown, MarkdownWithToc, find_testable_code, old_find_testable_code};
use html::markdown::RenderType;
use test::{TestOptions, Collector};

/// Separate any lines at the start of the file that begin with `# ` or `%`.
fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) {
    let mut metadata = Vec::new();
    let mut count = 0;

    for line in s.lines() {
        if line.starts_with("# ") || line.starts_with("%") {
            // trim the whitespace after the symbol
            metadata.push(line[1..].trim_left());
            count += line.len() + 1;
        } else {
            return (metadata, &s[count..]);
        }
    }

    // if we're here, then all lines were metadata `# ` or `%` lines.
    (metadata, "")
}

/// Render `input` (e.g. "foo.md") into an HTML file in `output`
/// (e.g. output = "bar" => "bar/foo.html").
pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
              external_html: &ExternalHtml, include_toc: bool,
              render_type: RenderType) -> isize {
    let input_p = Path::new(input);
    output.push(input_p.file_stem().unwrap());
    output.set_extension("html");

    let mut css = String::new();
    for name in &matches.opt_strs("markdown-css") {
        let s = format!("<link rel=\"stylesheet\" type=\"text/css\" href=\"{}\">\n", name);
        css.push_str(&s)
    }

    let input_str = match load_string(input) {
        Ok(s) => s,
        Err(LoadStringError::ReadFail) => return 1,
        Err(LoadStringError::BadUtf8) => return 2,
    };
    if let Some(playground) = matches.opt_str("markdown-playground-url").or(
                              matches.opt_str("playground-url")) {
        markdown::PLAYGROUND.with(|s| { *s.borrow_mut() = Some((None, playground)); });
    }

    let mut out = match File::create(&output) {
        Err(e) => {
            let _ = writeln!(&mut io::stderr(),
                             "rustdoc: {}: {}",
                             output.display(), e);
            return 4;
        }
        Ok(f) => f
    };

    let (metadata, text) = extract_leading_metadata(&input_str);
    if metadata.is_empty() {
        let _ = writeln!(
            &mut io::stderr(),
            "rustdoc: invalid markdown file: no initial lines starting with `# ` or `%`"
        );
        return 5;
    }
    let title = metadata[0];

    reset_ids(false);

    let rendered = if include_toc {
        format!("{}", MarkdownWithToc(text, render_type))
    } else {
        format!("{}", Markdown(text, render_type))
    };

    let err = write!(
        &mut out,
        r#"<!DOCTYPE html>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="generator" content="rustdoc">
    <title>{title}</title>

    {css}
    {in_header}

    {before_content}

{title}

    {text}
    {after_content}

"#,
        title = Escape(title),
        css = css,
        in_header = external_html.in_header,
        before_content = external_html.before_content,
        text = rendered,
        after_content = external_html.after_content,
        );

    match err {
        Err(e) => {
            let _ = writeln!(&mut io::stderr(),
                             "rustdoc: cannot write to `{}`: {}",
                             output.display(), e);
            6
        }
        Ok(_) => 0
    }
}

/// Run any tests/code examples in the markdown file `input`.
pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
            mut test_args: Vec<String>, maybe_sysroot: Option<PathBuf>,
            render_type: RenderType, display_warnings: bool) -> isize {
    let input_str = match load_string(input) {
        Ok(s) => s,
        Err(LoadStringError::ReadFail) => return 1,
        Err(LoadStringError::BadUtf8) => return 2,
    };

    let mut opts = TestOptions::default();
    opts.no_crate_inject = true;
    let mut collector = Collector::new(input.to_string(), cfgs, libs, externs,
                                       true, opts, maybe_sysroot, None,
                                       Some(input.to_owned()),
                                       render_type);
    old_find_testable_code(&input_str, &mut collector, DUMMY_SP);
    find_testable_code(&input_str, &mut collector, DUMMY_SP);
    test_args.insert(0, "rustdoctest".to_string());
    testing::test_main(&test_args, collector.tests,
                       testing::Options::new().display_output(display_warnings));
    0
}
<commit_msg>rustdoc: Don't run Markdown tests twice<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 std::default::Default;
use std::fs::File;
use std::io::prelude::*;
use std::io;
use std::path::{PathBuf, Path};

use getopts;
use testing;
use rustc::session::search_paths::SearchPaths;
use rustc::session::config::Externs;
use syntax::codemap::DUMMY_SP;

use externalfiles::{ExternalHtml, LoadStringError, load_string};

use html::render::reset_ids;
use html::escape::Escape;
use html::markdown;
use html::markdown::{Markdown, MarkdownWithToc, find_testable_code, old_find_testable_code};
use html::markdown::RenderType;
use test::{TestOptions, Collector};

/// Separate any lines at the start of the file that begin with `# ` or `%`.
fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) {
    let mut metadata = Vec::new();
    let mut count = 0;

    for line in s.lines() {
        if line.starts_with("# ") || line.starts_with("%") {
            // trim the whitespace after the symbol
            metadata.push(line[1..].trim_left());
            count += line.len() + 1;
        } else {
            return (metadata, &s[count..]);
        }
    }

    // if we're here, then all lines were metadata `# ` or `%` lines.
    (metadata, "")
}

/// Render `input` (e.g. "foo.md") into an HTML file in `output`
/// (e.g. output = "bar" => "bar/foo.html").
pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
              external_html: &ExternalHtml, include_toc: bool,
              render_type: RenderType) -> isize {
    let input_p = Path::new(input);
    output.push(input_p.file_stem().unwrap());
    output.set_extension("html");

    let mut css = String::new();
    for name in &matches.opt_strs("markdown-css") {
        let s = format!("<link rel=\"stylesheet\" type=\"text/css\" href=\"{}\">\n", name);
        css.push_str(&s)
    }

    let input_str = match load_string(input) {
        Ok(s) => s,
        Err(LoadStringError::ReadFail) => return 1,
        Err(LoadStringError::BadUtf8) => return 2,
    };
    if let Some(playground) = matches.opt_str("markdown-playground-url").or(
                              matches.opt_str("playground-url")) {
        markdown::PLAYGROUND.with(|s| { *s.borrow_mut() = Some((None, playground)); });
    }

    let mut out = match File::create(&output) {
        Err(e) => {
            let _ = writeln!(&mut io::stderr(),
                             "rustdoc: {}: {}",
                             output.display(), e);
            return 4;
        }
        Ok(f) => f
    };

    let (metadata, text) = extract_leading_metadata(&input_str);
    if metadata.is_empty() {
        let _ = writeln!(
            &mut io::stderr(),
            "rustdoc: invalid markdown file: no initial lines starting with `# ` or `%`"
        );
        return 5;
    }
    let title = metadata[0];

    reset_ids(false);

    let rendered = if include_toc {
        format!("{}", MarkdownWithToc(text, render_type))
    } else {
        format!("{}", Markdown(text, render_type))
    };

    let err = write!(
        &mut out,
        r#"<!DOCTYPE html>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="generator" content="rustdoc">
    <title>{title}</title>

    {css}
    {in_header}

    {before_content}

{title}

    {text}
    {after_content}

"#,
        title = Escape(title),
        css = css,
        in_header = external_html.in_header,
        before_content = external_html.before_content,
        text = rendered,
        after_content = external_html.after_content,
        );

    match err {
        Err(e) => {
            let _ = writeln!(&mut io::stderr(),
                             "rustdoc: cannot write to `{}`: {}",
                             output.display(), e);
            6
        }
        Ok(_) => 0
    }
}

/// Run any tests/code examples in the markdown file `input`.
pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
            mut test_args: Vec<String>, maybe_sysroot: Option<PathBuf>,
            render_type: RenderType, display_warnings: bool) -> isize {
    let input_str = match load_string(input) {
        Ok(s) => s,
        Err(LoadStringError::ReadFail) => return 1,
        Err(LoadStringError::BadUtf8) => return 2,
    };

    let mut opts = TestOptions::default();
    opts.no_crate_inject = true;
    let mut collector = Collector::new(input.to_string(), cfgs, libs, externs,
                                       true, opts, maybe_sysroot, None,
                                       Some(input.to_owned()),
                                       render_type);
    if render_type == RenderType::Pulldown {
        old_find_testable_code(&input_str, &mut collector, DUMMY_SP);
        find_testable_code(&input_str, &mut collector, DUMMY_SP);
    } else {
        old_find_testable_code(&input_str, &mut collector, DUMMY_SP);
    }
    test_args.insert(0, "rustdoctest".to_string());
    testing::test_main(&test_args, collector.tests,
                       testing::Options::new().display_output(display_warnings));
    0
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 container::MutableSet;
use hashmap::HashSet;
use option::{Some, None, Option};
use vec::ImmutableVector;

/// Imports for old crate map versions
use cast::transmute;
use libc::c_char;
use ptr;
use str::raw::from_c_str;
use vec;

// Need to tell the linker on OS X to not barf on undefined symbols
// and instead look them up at runtime, which we need to resolve
// the crate_map properly.
#[cfg(target_os = "macos")]
#[link_args = "-undefined dynamic_lookup"]
extern {}

#[cfg(not(windows))]
extern {
    #[weak_linkage]
    #[link_name = "_rust_crate_map_toplevel"]
    static CRATE_MAP: CrateMap<'static>;
}

/// structs for old crate map versions
pub struct ModEntryV0 {
    name: *c_char,
    log_level: *mut u32
}
pub struct CrateMapV0 {
    entries: *ModEntryV0,
    children: [*CrateMapV0, ..1]
}

pub struct CrateMapV1 {
    version: i32,
    entries: *ModEntryV0,
    /// a dynamically sized struct, where all pointers to children are listed adjacent
    /// to the struct, terminated with NULL
    children: [*CrateMapV1, ..1]
}

pub struct ModEntry<'self> {
    name: &'self str,
    log_level: *mut u32
}

pub struct CrateMap<'self> {
    version: i32,
    entries: &'self [ModEntry<'self>],
    children: &'self [&'self CrateMap<'self>]
}

#[cfg(not(windows))]
pub fn get_crate_map() -> Option<&'static CrateMap<'static>> {
    let ptr: (*CrateMap) = &'static CRATE_MAP;
    if ptr.is_null() {
        return None;
    } else {
        return Some(&'static CRATE_MAP);
    }
}

#[cfg(windows)]
#[fixed_stack_segment]
#[inline(never)]
pub fn get_crate_map() -> Option<&'static CrateMap<'static>> {
    use c_str::ToCStr;
    use unstable::dynamic_lib::dl;

    let sym = unsafe {
        let module = dl::open_internal();
        let sym = do "__rust_crate_map_toplevel".with_c_str |buf| {
            dl::symbol(module, buf)
        };
        dl::close(module);
        sym
    };
    let ptr: (*CrateMap) = sym as *CrateMap;
    if ptr.is_null() {
        return None;
    } else {
        unsafe {
            return Some(transmute(sym));
        }
    }
}

fn version(crate_map: &CrateMap) -> i32 {
    match crate_map.version {
        2 => return 2,
        1 => return 1,
        _ => return 0
    }
}

fn iter_module_map(mod_entries: &[ModEntry], f: &fn(&ModEntry)) {
    for entry in mod_entries.iter() {
        f(entry);
    }
}

unsafe fn iter_module_map_v0(entries: *ModEntryV0, f: &fn(&ModEntry)) {
    let mut curr = entries;
    while !(*curr).name.is_null() {
        let mod_entry = ModEntry { name: from_c_str((*curr).name), log_level: (*curr).log_level };
        f(&mod_entry);
        curr = curr.offset(1);
    }
}

fn do_iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry),
                            visited: &mut HashSet<*CrateMap<'a>>) {
    if visited.insert(crate_map as *CrateMap) {
        match version(crate_map) {
            2 => {
                let (entries, children) = (crate_map.entries, crate_map.children);
                iter_module_map(entries, |x| f(x));
                for child in children.iter() {
                    do_iter_crate_map(*child, |x| f(x), visited);
                }
            },
            // code for old crate map versions
            1 => unsafe {
                let v1: *CrateMapV1 = transmute(crate_map);
                iter_module_map_v0((*v1).entries, |x| f(x));
                let children = vec::raw::to_ptr((*v1).children);
                do ptr::array_each(children) |child| {
                    do_iter_crate_map(transmute(child), |x| f(x), visited);
                }
            },
            0 => unsafe {
                let v0: *CrateMapV0 = transmute(crate_map);
                iter_module_map_v0((*v0).entries, |x| f(x));
                let children = vec::raw::to_ptr((*v0).children);
                do ptr::array_each(children) |child| {
                    do_iter_crate_map(transmute(child), |x| f(x), visited);
                }
            },
            _ => fail2!("invalid crate map version")
        }
    }
}

/// Iterates recursively over `crate_map` and all child crate maps
pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry)) {
    // XXX: use random numbers as keys from the OS-level RNG when there is a nice
    //        way to do this
    let mut v: HashSet<*CrateMap<'a>> = HashSet::with_capacity_and_keys(0, 0, 32);
    do_iter_crate_map(crate_map, f, &mut v);
}

#[cfg(test)]
mod tests {
    use rt::crate_map::{CrateMap, ModEntry, iter_crate_map};

    #[test]
    fn iter_crate_map_duplicates() {
        let mut level3: u32 = 3;

        let entries = [
            ModEntry { name: "c::m1", log_level: &mut level3},
        ];

        let child_crate = CrateMap {
            version: 2,
            entries: entries,
            children: []
        };

        let root_crate = CrateMap {
            version: 2,
            entries: [],
            children: [&child_crate, &child_crate]
        };

        let mut cnt = 0;
        unsafe {
            do iter_crate_map(&root_crate) |entry| {
                assert!(*entry.log_level == 3);
                cnt += 1;
            }
            assert!(cnt == 1);
        }
    }

    #[test]
    fn iter_crate_map_follow_children() {
        let mut level2: u32 = 2;
        let mut level3: u32 = 3;
        let child_crate2 = CrateMap {
            version: 2,
            entries: [
                ModEntry { name: "c::m1", log_level: &mut level2},
                ModEntry { name: "c::m2", log_level: &mut level3},
            ],
            children: []
        };

        let child_crate1 = CrateMap {
            version: 2,
            entries: [
                ModEntry { name: "t::f1", log_level: &mut 1},
            ],
            children: [&child_crate2]
        };

        let root_crate = CrateMap {
            version: 2,
            entries: [
                ModEntry { name: "t::f2", log_level: &mut 0},
            ],
            children: [&child_crate1]
        };

        let mut cnt = 0;
        unsafe {
            do iter_crate_map(&root_crate) |entry| {
                assert!(*entry.log_level == cnt);
                cnt += 1;
            }
            assert!(cnt == 4);
        }
    }

    /// Tests for old crate map versions
    #[test]
    fn iter_crate_map_duplicates_v1() {
        use c_str::ToCStr;
        use cast::transmute;
        use ptr;
        use rt::crate_map::{CrateMapV1, ModEntryV0, iter_crate_map};
        use vec;

        struct CrateMapT3 {
            version: i32,
            entries: *ModEntryV0,
            children: [*CrateMapV1, ..3]
        }

        unsafe {
            let mod_name1 = "c::m1".to_c_str();
            let mut level3: u32 = 3;

            let entries: ~[ModEntryV0] = ~[
                ModEntryV0 { name: mod_name1.with_ref(|buf| buf), log_level: &mut level3},
                ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()}
            ];
            let child_crate = CrateMapV1 {
                version: 1,
                entries: vec::raw::to_ptr(entries),
                children: [ptr::null()]
            };

            let root_crate = CrateMapT3 {
                version: 1,
                entries: vec::raw::to_ptr([
                    ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()}
                ]),
                children: [&child_crate as *CrateMapV1, &child_crate as *CrateMapV1, ptr::null()]
            };

            let mut cnt = 0;
            do iter_crate_map(transmute(&root_crate)) |entry| {
                assert!(*(*entry).log_level == 3);
                cnt += 1;
            }
            assert!(cnt == 1);
        }
    }

    #[test]
    fn iter_crate_map_follow_children_v1() {
        use c_str::ToCStr;
        use cast::transmute;
        use ptr;
        use rt::crate_map::{CrateMapV1, ModEntryV0, iter_crate_map};
        use vec;

        struct CrateMapT2 {
            version: i32,
            entries: *ModEntryV0,
            children: [*CrateMapV1, ..2]
        }

        unsafe {
            let mod_name1 = "c::m1".to_c_str();
            let mod_name2 = "c::m2".to_c_str();
            let mut level2: u32 = 2;
            let mut level3: u32 = 3;
            let child_crate2 = CrateMapV1 {
                version: 1,
                entries: vec::raw::to_ptr([
                    ModEntryV0 { name: mod_name1.with_ref(|buf| buf), log_level: &mut level2},
                    ModEntryV0 { name: mod_name2.with_ref(|buf| buf), log_level: &mut level3},
                    ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()}
                ]),
                children: [ptr::null()]
            };

            let child_crate1 = CrateMapT2 {
                version: 1,
                entries: vec::raw::to_ptr([
                    ModEntryV0 { name: "t::f1".with_c_str(|buf| buf), log_level: &mut 1},
                    ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()}
                ]),
                children: [&child_crate2 as *CrateMapV1, ptr::null()]
            };

            let child_crate1_ptr: *CrateMapV1 = transmute(&child_crate1);
            let root_crate = CrateMapT2 {
                version: 1,
                entries: vec::raw::to_ptr([
                    ModEntryV0 { name: "t::f1".with_c_str(|buf| buf), log_level: &mut 0},
                    ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()}
                ]),
                children: [child_crate1_ptr, ptr::null()]
            };

            let mut cnt = 0;
            do iter_crate_map(transmute(&root_crate)) |entry| {
                assert!(*(*entry).log_level == cnt);
                cnt += 1;
            }
            assert!(cnt == 4);
        }
    }
}
<commit_msg>auto merge of #9809 : fhahn/rust/remove-old-cratemap-code, r=alexcrichton<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 container::MutableSet;
use hashmap::HashSet;
use option::{Some, None, Option};
use vec::ImmutableVector;

// Need to tell the linker on OS X to not barf on undefined symbols
// and instead look them up at runtime, which we need to resolve
// the crate_map properly.
#[cfg(target_os = "macos")]
#[link_args = "-undefined dynamic_lookup"]
extern {}

pub struct ModEntry<'self> {
    name: &'self str,
    log_level: *mut u32
}

pub struct CrateMap<'self> {
    version: i32,
    entries: &'self [ModEntry<'self>],
    children: &'self [&'self CrateMap<'self>]
}

#[cfg(not(windows))]
pub fn get_crate_map() -> Option<&'static CrateMap<'static>> {
    extern {
        #[weak_linkage]
        #[link_name = "_rust_crate_map_toplevel"]
        static CRATE_MAP: CrateMap<'static>;
    }

    let ptr: (*CrateMap) = &'static CRATE_MAP;
    if ptr.is_null() {
        return None;
    } else {
        return Some(&'static CRATE_MAP);
    }
}

#[cfg(windows)]
#[fixed_stack_segment]
#[inline(never)]
pub fn get_crate_map() -> Option<&'static CrateMap<'static>> {
    use cast::transmute;
    use c_str::ToCStr;
    use unstable::dynamic_lib::dl;

    let sym = unsafe {
        let module = dl::open_internal();
        let sym = do "__rust_crate_map_toplevel".with_c_str |buf| {
            dl::symbol(module, buf)
        };
        dl::close(module);
        sym
    };
    let ptr: (*CrateMap) = sym as *CrateMap;
    if ptr.is_null() {
        return None;
    } else {
        unsafe {
            return Some(transmute(sym));
        }
    }
}

fn version(crate_map: &CrateMap) -> i32 {
    match crate_map.version {
        2 => return 2,
        _ => return 0
    }
}

fn do_iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry),
                            visited: &mut HashSet<*CrateMap<'a>>) {
    if visited.insert(crate_map as *CrateMap) {
        match version(crate_map) {
            2 => {
                let (entries, children) = (crate_map.entries, crate_map.children);
                for entry in entries.iter() {
                    f(entry);
                }
                for child in children.iter() {
                    do_iter_crate_map(*child, |x| f(x), visited);
                }
            },
            _ => fail2!("invalid crate map version")
        }
    }
}

/// Iterates recursively over `crate_map` and all child crate maps
pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry)) {
    // XXX: use random numbers as keys from the OS-level RNG when there is a nice
    //        way to do this
    let mut v: HashSet<*CrateMap<'a>> = HashSet::with_capacity_and_keys(0, 0, 32);
    do_iter_crate_map(crate_map, f, &mut v);
}

#[cfg(test)]
mod tests {
    use rt::crate_map::{CrateMap, ModEntry, iter_crate_map};

    #[test]
    fn iter_crate_map_duplicates() {
        let mut level3: u32 = 3;

        let entries = [
            ModEntry { name: "c::m1", log_level: &mut level3},
        ];

        let child_crate = CrateMap {
            version: 2,
            entries: entries,
            children: []
        };

        let root_crate = CrateMap {
            version: 2,
            entries: [],
            children: [&child_crate, &child_crate]
        };

        let mut cnt = 0;
        unsafe {
            do iter_crate_map(&root_crate) |entry| {
                assert!(*entry.log_level == 3);
                cnt += 1;
            }
            assert!(cnt == 1);
        }
    }

    #[test]
    fn iter_crate_map_follow_children() {
        let mut level2: u32 = 2;
        let mut level3: u32 = 3;
        let child_crate2 = CrateMap {
            version: 2,
            entries: [
                ModEntry { name: "c::m1", log_level: &mut level2},
                ModEntry { name: "c::m2", log_level: &mut level3},
            ],
            children: []
        };

        let child_crate1 = CrateMap {
            version: 2,
            entries: [
                ModEntry { name: "t::f1", log_level: &mut 1},
            ],
            children: [&child_crate2]
        };

        let root_crate = CrateMap {
            version: 2,
            entries: [
                ModEntry { name: "t::f2", log_level: &mut 0},
            ],
            children: [&child_crate1]
        };

        let mut cnt = 0;
        unsafe {
            do iter_crate_map(&root_crate) |entry| {
                assert!(*entry.log_level == cnt);
                cnt += 1;
            }
            assert!(cnt == 4);
        }
    }
}
<|endoftext|>


<commit_before>//! lapin-async
//!
//! this library is meant for use in an event loop. The library exposes, through the
//! [Connection struct](https://docs.rs/lapin-async/0.1.0/lapin_async/connection/struct.Connection.html),
//! a state machine you can drive through IO you manage.
//!
//! Typically, your code would own the socket and buffers, and regularly pass the
//! input and output buffers to the state machine so it receives messages and
//! serializes new ones to send. You can then query the current state and see
//! if it received new messages for the consumers.
//!
//! ## Creating a new connection
//!
//! Set up an AMQP 0.9.1 compliant server. For the purpose of this documentation,
//! we'll assume it is listening on `127.0.0.1:5672`.
//!
//! Create the client socket and some buffers to move data:
//!
//! ```rust,ignore
//! extern crate lapin_async as lapin;
//!
//! use std::net::TcpStream;
//! use lapin::connection::*;
//! use lapin::buffer::Buffer;
//!
//! fn main() {
//!   let mut stream = TcpStream::connect("127.0.0.1:5672").unwrap();
//!   stream.set_nonblocking(true);
//!
//!   let capacity = 8192;
//!   let mut send_buffer    = Buffer::with_capacity(capacity as usize);
//!   let mut receive_buffer = Buffer::with_capacity(capacity as usize);
//!
//! }
//! ```
//!
//! Now, we can create the `Connection` object:
//!
//! ```rust,ignore
//!   let mut conn: Connection = Connection::new();
//!   conn.set_frame_max(capacity);
//!   loop {
//!     match conn.run(&mut stream, &mut send_buffer, &mut receive_buffer) {
//!       Err(e) => panic!("could not connect: {:?}", e),
//!         Ok(ConnectionState::Connected) => break,
//!         Ok(state) => println!("now at state {:?}, continue", state),
//!       }
//!     thread::sleep(time::Duration::from_millis(100));
//!   }
//!   println!("CONNECTED");
//!
//!   let frame_max = conn.configuration.frame_max;
//!   if frame_max > capacity {
//!     send_buffer.grow(frame_max as usize);
//!     receive_buffer.grow(frame_max as usize);
//!   }
//!
//! ```
//!
//! The [`run` method](https://docs.rs/lapin-async/0.1.0/lapin_async/connection/struct.Connection.html#method.run)
//! will repeatedly call 3 other methods:
//!
//! - [`read_from_stream`](https://docs.rs/lapin-async/0.1.0/lapin_async/connection/struct.Connection.html#method.read_from_stream) with the input buffer. This method is only there as a helper to get data from the network into a `Buffer` struct, you might want to handle reading yourself
//! - [`parse`](https://docs.rs/lapin-async/0.1.0/lapin_async/connection/struct.Connection.html#method.parse) will parse the data you just gathered, update the state, and return the current state and how much bytes were consumed
//! - then you must call [`write_to_stream`](https://docs.rs/lapin-async/0.1.0/lapin_async/connection/struct.Connection.html#method.write_to_stream) in case the state machine must send messages to the server. It returns how much data was consumed and the current state
//!
//! Calling `parse` and `write_to_stream` is how you handle the plumbing for the state machine.
//! Your code should then react to the state changes returned by those functions, or to the
//! specific state of channels and consumers.
//!
//! In the current case, we wait until the state machine gets to the `ConnectionState::Connected` state.
//!
//! ## Creating a channel
//!
//! ```rust,ignore
//! let channel_id: u16 = conn.create_channel().unwrap();
//! conn.channel_open(channel_a, "".to_string()).expect("channel_open");
//!
//! // update state here until:
//! assert!(conn.check_state(channel_id, ChannelState::Connected).unwrap_or(false));
//! ```
//!
//! ## Creating a queue
//!
//! ```rust,ignore
//! //create the "hello" queue
//! let request_id: u16 = conn.queue_declare(channel_id, 0, "hello".to_string(), false, false, false, false, false, HashMap::new()).unwrap();
//!
//! // update state here until:
//! assert!(conn.is_finished(request_id).unwrap_or(false));
//! ```
//!
//! ## Publishing a message
//!
//! ```rust,ignore
//! conn.basic_publish(channel_id, 0, "".to_string(), "hello".to_string(), false, false).expect("basic_publish");
//! let payload = b"Hello world!";
//! conn.send_content_frames(channel_a, 60, payload, basic::Properties::default()));
//!
//! // update state
//! ```
//!
//! ## Creating a Consumer
//!
//! ```rust,ignore
//! //create the "hello" queue
//! let request_id: u16 = conn.basic_consume(channel_id, 0, "hello".to_string(), "my_consumer".to_string(), false, true, false, false, HashMap::new()).expect("basic_consume");
//!
//! // update state here until:
//! assert!(conn.is_finished(request_id).unwrap_or(false));
//!
//! // get the next message
//! if let Ok(message) = conn.next_message(channel_id, "hello", "my_consumer") {
//!  // handle message
//! }
//! ```

extern crate amq_protocol;
#[macro_use]
extern crate failure;
#[macro_use]
extern crate log;
extern crate nom;
extern crate cookie_factory;
extern crate sasl;

pub mod buffer;
pub mod io;
pub mod connection;
pub mod consumer;
pub mod channel;
pub mod queue;
pub mod message;
pub mod api;
pub mod error;
pub mod types;
pub mod uri;
<commit_msg>async: silence warning<commit_after>//! lapin-async
//!
//! this library is meant for use in an event loop. The library exposes, through the
//! [Connection struct](https://docs.rs/lapin-async/0.1.0/lapin_async/connection/struct.Connection.html),
//! a state machine you can drive through IO you manage.
//!
//! Typically, your code would own the socket and buffers, and regularly pass the
//! input and output buffers to the state machine so it receives messages and
//! serializes new ones to send. You can then query the current state and see
//! if it received new messages for the consumers.
//!
//! ## Creating a new connection
//!
//! Set up an AMQP 0.9.1 compliant server. For the purpose of this documentation,
//! we'll assume it is listening on `127.0.0.1:5672`.
//!
//! Create the client socket and some buffers to move data:
//!
//! ```rust,ignore
//! extern crate lapin_async as lapin;
//!
//! use std::net::TcpStream;
//! use lapin::connection::*;
//! use lapin::buffer::Buffer;
//!
//! fn main() {
//!   let mut stream = TcpStream::connect("127.0.0.1:5672").unwrap();
//!   stream.set_nonblocking(true);
//!
//!   let capacity = 8192;
//!   let mut send_buffer    = Buffer::with_capacity(capacity as usize);
//!   let mut receive_buffer = Buffer::with_capacity(capacity as usize);
//!
//! }
//! ```
//!
//! Now, we can create the `Connection` object:
//!
//! ```rust,ignore
//!   let mut conn: Connection = Connection::new();
//!   conn.set_frame_max(capacity);
//!   loop {
//!     match conn.run(&mut stream, &mut send_buffer, &mut receive_buffer) {
//!       Err(e) => panic!("could not connect: {:?}", e),
//!         Ok(ConnectionState::Connected) => break,
//!         Ok(state) => println!("now at state {:?}, continue", state),
//!       }
//!     thread::sleep(time::Duration::from_millis(100));
//!   }
//!   println!("CONNECTED");
//!
//!   let frame_max = conn.configuration.frame_max;
//!   if frame_max > capacity {
//!     send_buffer.grow(frame_max as usize);
//!     receive_buffer.grow(frame_max as usize);
//!   }
//!
//! ```
//!
//! The [`run` method](https://docs.rs/lapin-async/0.1.0/lapin_async/connection/struct.Connection.html#method.run)
//! will repeatedly call 3 other methods:
//!
//! - [`read_from_stream`](https://docs.rs/lapin-async/0.1.0/lapin_async/connection/struct.Connection.html#method.read_from_stream) with the input buffer. This method is only there as a helper to get data from the network into a `Buffer` struct, you might want to handle reading yourself
//! - [`parse`](https://docs.rs/lapin-async/0.1.0/lapin_async/connection/struct.Connection.html#method.parse) will parse the data you just gathered, update the state, and return the current state and how much bytes were consumed
//! - then you must call [`write_to_stream`](https://docs.rs/lapin-async/0.1.0/lapin_async/connection/struct.Connection.html#method.write_to_stream) in case the state machine must send messages to the server. It returns how much data was consumed and the current state
//!
//! Calling `parse` and `write_to_stream` is how you handle the plumbing for the state machine.
//! Your code should then react to the state changes returned by those functions, or to the
//! specific state of channels and consumers.
//!
//! In the current case, we wait until the state machine gets to the `ConnectionState::Connected` state.
//!
//! ## Creating a channel
//!
//! ```rust,ignore
//! let channel_id: u16 = conn.create_channel().unwrap();
//! conn.channel_open(channel_a, "".to_string()).expect("channel_open");
//!
//! // update state here until:
//! assert!(conn.check_state(channel_id, ChannelState::Connected).unwrap_or(false));
//! ```
//!
//! ## Creating a queue
//!
//! ```rust,ignore
//! //create the "hello" queue
//! let request_id: u16 = conn.queue_declare(channel_id, 0, "hello".to_string(), false, false, false, false, false, HashMap::new()).unwrap();
//!
//! // update state here until:
//! assert!(conn.is_finished(request_id).unwrap_or(false));
//! ```
//!
//! ## Publishing a message
//!
//! ```rust,ignore
//! conn.basic_publish(channel_id, 0, "".to_string(), "hello".to_string(), false, false).expect("basic_publish");
//! let payload = b"Hello world!";
//! conn.send_content_frames(channel_a, 60, payload, basic::Properties::default()));
//!
//! // update state
//! ```
//!
//! ## Creating a Consumer
//!
//! ```rust,ignore
//! //create the "hello" queue
//! let request_id: u16 = conn.basic_consume(channel_id, 0, "hello".to_string(), "my_consumer".to_string(), false, true, false, false, HashMap::new()).expect("basic_consume");
//!
//! // update state here until:
//! assert!(conn.is_finished(request_id).unwrap_or(false));
//!
//! // get the next message
//! if let Ok(message) = conn.next_message(channel_id, "hello", "my_consumer") {
//!  // handle message
//! }
//! ```

extern crate amq_protocol;
extern crate failure;
#[macro_use]
extern crate log;
extern crate nom;
extern crate cookie_factory;
extern crate sasl;

pub mod buffer;
pub mod io;
pub mod connection;
pub mod consumer;
pub mod channel;
pub mod queue;
pub mod message;
pub mod api;
pub mod error;
pub mod types;
pub mod uri;
<|endoftext|>


<commit_before>// Copyright 2020 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.

use grin_core as core;
use grin_store as store;
use grin_util as util;

use crate::core::global;
use crate::core::ser::{self, Readable, Reader, Writeable, Writer};
use std::fs;

const WRITE_CHUNK_SIZE: usize = 20;
const TEST_ALLOC_SIZE: usize = store::lmdb::ALLOC_CHUNK_SIZE_DEFAULT / 8 / WRITE_CHUNK_SIZE;

#[derive(Clone)]
struct PhatChunkStruct {
	phatness: u64,
}

impl PhatChunkStruct {
	/// create
	pub fn new() -> PhatChunkStruct {
		PhatChunkStruct { phatness: 0 }
	}
}

impl Readable for PhatChunkStruct {
	fn read<R: Reader>(reader: &mut R) -> Result<PhatChunkStruct, ser::Error> {
		let mut retval = PhatChunkStruct::new();
		for _ in 0..TEST_ALLOC_SIZE {
			retval.phatness = reader.read_u64()?;
		}
		Ok(retval)
	}
}

impl Writeable for PhatChunkStruct {
	fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
		// write many times
		for _ in 0..TEST_ALLOC_SIZE {
			writer.write_u64(self.phatness)?;
		}
		Ok(())
	}
}

fn clean_output_dir(test_dir: &str) {
	let _ = fs::remove_dir_all(test_dir);
}

fn setup(test_dir: &str) {
	global::set_local_chain_type(global::ChainTypes::Mainnet);
	util::init_test_logger();
	clean_output_dir(test_dir);
}

#[test]
fn lmdb_allocate() -> Result<(), store::Error> {
	let test_dir = "test_output/lmdb_allocate";
	setup(test_dir);
	// Allocate more than the initial chunk, ensuring
	// the DB resizes underneath
	{
		let store = store::Store::new(test_dir, Some("test1"), None, None)?;

		for i in 0..WRITE_CHUNK_SIZE * 2 {
			println!("Allocating chunk: {}", i);
			let chunk = PhatChunkStruct::new();
			let key_val = format!("phat_chunk_set_1_{}", i);
			let batch = store.batch()?;
			let key = store::to_key(b'P', &key_val);
			batch.put_ser(&key, &chunk)?;
			batch.commit()?;
		}
	}
	println!("***********************************");
	println!("***************NEXT*****************");
	println!("***********************************");
	// Open env again and keep adding
	{
		let store = store::Store::new(test_dir, Some("test1"), None, None)?;
		for i in 0..WRITE_CHUNK_SIZE * 2 {
			println!("Allocating chunk: {}", i);
			let chunk = PhatChunkStruct::new();
			let key_val = format!("phat_chunk_set_2_{}", i);
			let batch = store.batch()?;
			let key = store::to_key(b'P', &key_val);
			batch.put_ser(&key, &chunk)?;
			batch.commit()?;
		}
	}

	Ok(())
}
<commit_msg>add test coverage around existing behavior for exists() and iter() (#3452)<commit_after>// Copyright 2020 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.

use grin_core as core;
use grin_store as store;
use grin_util as util;
use store::SerIterator;

use crate::core::global;
use crate::core::ser::{self, Readable, Reader, Writeable, Writer};
use std::fs;

const WRITE_CHUNK_SIZE: usize = 20;
const TEST_ALLOC_SIZE: usize = store::lmdb::ALLOC_CHUNK_SIZE_DEFAULT / 8 / WRITE_CHUNK_SIZE;

#[derive(Clone)]
struct PhatChunkStruct {
	phatness: u64,
}

impl PhatChunkStruct {
	/// create
	pub fn new() -> PhatChunkStruct {
		PhatChunkStruct { phatness: 0 }
	}
}

impl Readable for PhatChunkStruct {
	fn read<R: Reader>(reader: &mut R) -> Result<PhatChunkStruct, ser::Error> {
		let mut retval = PhatChunkStruct::new();
		for _ in 0..TEST_ALLOC_SIZE {
			retval.phatness = reader.read_u64()?;
		}
		Ok(retval)
	}
}

impl Writeable for PhatChunkStruct {
	fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
		// write many times
		for _ in 0..TEST_ALLOC_SIZE {
			writer.write_u64(self.phatness)?;
		}
		Ok(())
	}
}

fn clean_output_dir(test_dir: &str) {
	let _ = fs::remove_dir_all(test_dir);
}

fn setup(test_dir: &str) {
	global::set_local_chain_type(global::ChainTypes::Mainnet);
	util::init_test_logger();
	clean_output_dir(test_dir);
}

#[test]
fn test_exists() -> Result<(), store::Error> {
	let test_dir = "target/test_exists";
	setup(test_dir);

	let store = store::Store::new(test_dir, Some("test1"), None, None)?;

	let key = [0, 0, 0, 1];
	let value = [1, 1, 1, 1];

	// Start new batch and insert a new key/value entry.
	let batch = store.batch()?;
	batch.put(&key, &value)?;

	// Check we can see the new entry in uncommitted batch.
	assert!(batch.exists(&key)?);

	// Check we cannot see the new entry yet outside of the uncommitted batch.
	assert!(!store.exists(&key)?);

	batch.commit()?;

	// Check we can see the new entry after committing the batch.
	assert!(store.exists(&key)?);

	clean_output_dir(test_dir);
	Ok(())
}

#[test]
fn test_iter() -> Result<(), store::Error> {
	let test_dir = "target/test_iter";
	setup(test_dir);

	let store = store::Store::new(test_dir, Some("test1"), None, None)?;

	let key = [0, 0, 0, 1];
	let value = [1, 1, 1, 1];

	// Start new batch and insert a new key/value entry.
	let batch = store.batch()?;
	batch.put(&key, &value)?;

	// TODO - This is not currently possible (and we need to be aware of this).
	// Currently our SerIterator is limited to using a ReadTransaction only.
	//
	// Check we can see the new entry via an iterator using the uncommitted batch.
	// let mut iter: SerIterator<Vec<u8>> = batch.iter(&[0])?;
	// assert_eq!(iter.next(), Some((key.to_vec(), value.to_vec())));
	// assert_eq!(iter.next(), None);

	// Check we can not yet see the new entry via an iterator outside the uncommitted batch.
	let mut iter: SerIterator<Vec<u8>> = store.iter(&[0])?;
	assert_eq!(iter.next(), None);

	batch.commit()?;

	// Check we can see the new entry via an iterator after committing the batch.
	let mut iter: SerIterator<Vec<u8>> = store.iter(&[0])?;
	assert_eq!(iter.next(), Some((key.to_vec(), value.to_vec())));
	assert_eq!(iter.next(), None);

	clean_output_dir(test_dir);
	Ok(())
}

#[test]
fn lmdb_allocate() -> Result<(), store::Error> {
	let test_dir = "target/lmdb_allocate";
	setup(test_dir);
	// Allocate more than the initial chunk, ensuring
	// the DB resizes underneath
	{
		let store = store::Store::new(test_dir, Some("test1"), None, None)?;

		for i in 0..WRITE_CHUNK_SIZE * 2 {
			println!("Allocating chunk: {}", i);
			let chunk = PhatChunkStruct::new();
			let key_val = format!("phat_chunk_set_1_{}", i);
			let batch = store.batch()?;
			let key = store::to_key(b'P', &key_val);
			batch.put_ser(&key, &chunk)?;
			batch.commit()?;
		}
	}
	println!("***********************************");
	println!("***************NEXT*****************");
	println!("***********************************");
	// Open env again and keep adding
	{
		let store = store::Store::new(test_dir, Some("test1"), None, None)?;
		for i in 0..WRITE_CHUNK_SIZE * 2 {
			println!("Allocating chunk: {}", i);
			let chunk = PhatChunkStruct::new();
			let key_val = format!("phat_chunk_set_2_{}", i);
			let batch = store.batch()?;
			let key = store::to_key(b'P', &key_val);
			batch.put_ser(&key, &chunk)?;
			batch.commit()?;
		}
	}

	Ok(())
}
<|endoftext|>