<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 crate::varint;
use bufsize::SizeCounter;
use bytes::buf::ext::Chain;
use bytes::{Buf, BufMut, Bytes, BytesMut};
use std::io::Cursor;

pub trait BufExt: Buf {
    /// Reset buffer back to the beginning.
    fn reset(self) -> Self;

    fn copy_to_bytes(&mut self, len: usize) -> Bytes;
}

impl BufExt for Cursor<Bytes> {
    fn reset(self) -> Self {
        Cursor::new(self.into_inner())
    }

    fn copy_to_bytes(&mut self, len: usize) -> Bytes {
        // This is available as standard in Bytes 1.0
        let pos = self.position() as usize;
        let end = pos + len;
        // Panics if len is too large (same as Bytes 1.0)
        let bytes = self.get_ref().slice(pos..end);
        self.set_position(end as u64);
        bytes
    }
}

impl<T: AsRef<[u8]> + ?Sized> BufExt for Cursor<&T> {
    fn reset(self) -> Self {
        Cursor::new(self.into_inner())
    }

    fn copy_to_bytes(&mut self, len: usize) -> Bytes {
        // This is available as standard in Bytes 1.0
        let pos = self.position() as usize;
        let end = pos + len;
        // Panics if len is too large (same as Bytes 1.0)
        let all = self.get_ref().as_ref();
        let bytes = Bytes::copy_from_slice(&all[pos..end]);
        self.set_position(end as u64);
        bytes
    }
}

impl<T: BufExt, U: BufExt> BufExt for Chain<T, U> {
    fn reset(self) -> Self {
        let (a, b) = self.into_inner();
        Chain::new(a.reset(), b.reset())
    }

    fn copy_to_bytes(&mut self, len: usize) -> Bytes {
        let a = self.first_mut();
        if a.has_remaining() {
            if a.remaining() >= len {
                a.copy_to_bytes(len)
            } else {
                // data is split across the two buffers
                assert!(self.remaining() >= len);
                let mut out = BytesMut::with_capacity(len);
                let mut remaining = len;
                while remaining > 0 {
                    let part = self.bytes();
                    let part_len = part.len().min(remaining);
                    out.copy_from_slice(&part[..part_len]);
                    self.advance(part_len);
                    remaining -= part_len;
                }
                out.freeze()
            }
        } else {
            self.last_mut().copy_to_bytes(len)
        }
    }
}

pub trait BufMutExt: BufMut {
    type Final: Send + 'static;

    fn put_varint_u64(&mut self, v: u64)
    where
        Self: Sized,
    {
        varint::write_u64(self, v)
    }

    fn put_varint_i64(&mut self, v: i64)
    where
        Self: Sized,
    {
        varint::write_u64(self, varint::zigzag(v))
    }

    fn finalize(self) -> Self::Final;
}

impl BufMutExt for BytesMut {
    type Final = Bytes;

    fn finalize(self) -> Self::Final {
        self.freeze()
    }
}

impl BufMutExt for SizeCounter {
    type Final = usize;

    #[inline]
    fn put_varint_u64(&mut self, v: u64) {
        self.put_uint(v, varint::u64_len(v));
    }

    #[inline]
    fn put_varint_i64(&mut self, v: i64) {
        self.put_int(v, varint::u64_len(varint::zigzag(v)));
    }

    #[inline]
    fn finalize(self) -> Self::Final {
        self.size()
    }
}

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

    #[test]
    fn test_bytes_reset() {
        let b = Bytes::from(b"hello, world".to_vec());
        let mut c = Cursor::new(b);

        assert_eq!(c.remaining(), 12);
        assert_eq!(c.get_u8(), b'h');

        c.advance(5);
        assert_eq!(c.remaining(), 6);
        assert_eq!(c.get_u8(), b' ');

        let mut c = c.reset();
        assert_eq!(c.remaining(), 12);
        assert_eq!(c.get_u8(), b'h');
    }

    #[test]
    fn test_empty_bytes_reset() {
        let b = Bytes::from(Vec::new());
        let c = Cursor::new(b);

        assert_eq!(c.remaining(), 0);

        let c = c.reset();
        assert_eq!(c.remaining(), 0);
    }
}
<commit_msg>rust: simplify thrift BufExt::copy_to_bytes for Chain<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 crate::varint;
use bufsize::SizeCounter;
use bytes::buf::ext::Chain;
use bytes::buf::BufExt as BufExtBytes;
use bytes::{Buf, BufMut, Bytes, BytesMut};
use std::io::Cursor;

pub trait BufExt: Buf {
    /// Reset buffer back to the beginning.
    fn reset(self) -> Self;

    fn copy_to_bytes(&mut self, len: usize) -> Bytes;
}

impl BufExt for Cursor<Bytes> {
    fn reset(self) -> Self {
        Cursor::new(self.into_inner())
    }

    fn copy_to_bytes(&mut self, len: usize) -> Bytes {
        // This is available as standard in Bytes 1.0
        let pos = self.position() as usize;
        let end = pos + len;
        // Panics if len is too large (same as Bytes 1.0)
        let bytes = self.get_ref().slice(pos..end);
        self.set_position(end as u64);
        bytes
    }
}

impl<T: AsRef<[u8]> + ?Sized> BufExt for Cursor<&T> {
    fn reset(self) -> Self {
        Cursor::new(self.into_inner())
    }

    fn copy_to_bytes(&mut self, len: usize) -> Bytes {
        // This is available as standard in Bytes 1.0
        let pos = self.position() as usize;
        let end = pos + len;
        // Panics if len is too large (same as Bytes 1.0)
        let all = self.get_ref().as_ref();
        let bytes = Bytes::copy_from_slice(&all[pos..end]);
        self.set_position(end as u64);
        bytes
    }
}

impl<T: BufExt, U: BufExt> BufExt for Chain<T, U> {
    fn reset(self) -> Self {
        let (a, b) = self.into_inner();
        Chain::new(a.reset(), b.reset())
    }

    fn copy_to_bytes(&mut self, len: usize) -> Bytes {
        self.take(len).to_bytes()
    }
}

pub trait BufMutExt: BufMut {
    type Final: Send + 'static;

    fn put_varint_u64(&mut self, v: u64)
    where
        Self: Sized,
    {
        varint::write_u64(self, v)
    }

    fn put_varint_i64(&mut self, v: i64)
    where
        Self: Sized,
    {
        varint::write_u64(self, varint::zigzag(v))
    }

    fn finalize(self) -> Self::Final;
}

impl BufMutExt for BytesMut {
    type Final = Bytes;

    fn finalize(self) -> Self::Final {
        self.freeze()
    }
}

impl BufMutExt for SizeCounter {
    type Final = usize;

    #[inline]
    fn put_varint_u64(&mut self, v: u64) {
        self.put_uint(v, varint::u64_len(v));
    }

    #[inline]
    fn put_varint_i64(&mut self, v: i64) {
        self.put_int(v, varint::u64_len(varint::zigzag(v)));
    }

    #[inline]
    fn finalize(self) -> Self::Final {
        self.size()
    }
}

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

    #[test]
    fn test_bytes_reset() {
        let b = Bytes::from(b"hello, world".to_vec());
        let mut c = Cursor::new(b);

        assert_eq!(c.remaining(), 12);
        assert_eq!(c.get_u8(), b'h');

        c.advance(5);
        assert_eq!(c.remaining(), 6);
        assert_eq!(c.get_u8(), b' ');

        let mut c = c.reset();
        assert_eq!(c.remaining(), 12);
        assert_eq!(c.get_u8(), b'h');
    }

    #[test]
    fn test_empty_bytes_reset() {
        let b = Bytes::from(Vec::new());
        let c = Cursor::new(b);

        assert_eq!(c.remaining(), 0);

        let c = c.reset();
        assert_eq!(c.remaining(), 0);
    }
}
<|endoftext|>


<commit_before>use std::collections::{HashSet, HashMap};
use std::cell::{Cell, RefCell};

use regexp::{Token, lex};

pub fn re2(search: String, into: &'static str) -> Result<(), ()> {
    Ok(())
}

#[derive(Debug)]
struct Production {
    from: String,
    to: Vec<String>,
}

impl Production {
    pub fn new<T: Into<String>>(from: T, to: Vec<T>) -> Production {

        let mut to_arr = vec![];
        for x in to {
            to_arr.push(x.into())
        }
        Production {
            from: from.into(),
            to: to_arr,
        }
    }
}

fn get_productions() -> Vec<Production> {
    let prods = vec![
        Production::new("Re", vec!["Lit", "Ops"]),
        Production::new("Re", vec!["(", "Re", ")", "Ops"]),

        Production::new("Ops", vec!["*", "ReL"]),
        Production::new("Ops", vec!["+", "ReL"]),
        Production::new("Ops", vec!["|", "Re"]),
        Production::new("Ops", vec!["Re"]),
        Production::new("Ops", vec!["Lambda"]),

        Production::new("ReL", vec!["Re"]),
        Production::new("ReL", vec!["Lambda"]),
    ];

    prods
}

fn get_table() -> HashMap<(String, String), usize> {
    let entries = [
       (("Re", "Lit"), 0),
       (("Re", "("), 1),

       (("Ops", "*"), 2),
       (("Ops", "+"), 3),
       (("Ops", "|"), 4),
       (("Ops", "Lit"), 5),
       (("Ops", "("), 5),
       (("Ops", "EOF"), 6),
       (("Ops", ")"), 6),
       (("Ops", "Lambda"), 6),

       (("ReL", "Lit"), 7),
       (("ReL", "("), 7),
       (("ReL", "EOF"), 8),
       (("ReL", ")"), 8),
       (("ReL", "Lambda"), 8),
    ];

    let mut table = HashMap::new();
    for &((non_terminal, token_cat), value) in entries.iter() {
        table.insert((non_terminal.to_string(), token_cat.to_string()), value);
    }

    //table.insert(("Re", "Lit"), 0);
    //table.insert(("Re", "("), 1);

    //table.insert(("Ops", "*"), 2);
    //table.insert(("Ops", "+"), 3);
    //table.insert(("Ops", "|"), 4);
    //table.insert(("Ops", "Lit"), 5);
    //table.insert(("Ops", "("), 5);
    //table.insert(("Ops", "eof"), 6);
    //table.insert(("Ops", ")"), 6);
    //table.insert(("Ops", "Lambda"), 6);

    //table.insert(("ReL", "Lit"), 7);
    //table.insert(("ReL", "("), 7);
    //table.insert(("ReL", "eof"), 8);
    //table.insert(("ReL", ")"), 8);
    //table.insert(("ReL", "Lambda"), 8);

    table
}

fn is_terminal(s: &String) -> bool {
    let t = vec![
        "Lit",
        "(",
        ")",
        "*",
        "+",
        "|",
        "EOF",
        "Lambda"
    ];

    let terminals: HashSet<String> = t.iter().cloned().map(|s| s.to_string()).collect();
    terminals.contains(s)
}

#[derive(Debug)]
struct Parser {
    pub index: usize,
    pub src: String,
    pub tokens: Vec<Token>,
    pub productions: Vec<Production>,
    pub table: HashMap<(String, String), usize>,
    stack: Vec<String>
}

impl Parser {
    pub fn new(src: String) -> Parser {
        let tokens = lex(src.clone());
        //let root = Node::new_nt("Re");
        Parser {
            index: 0,
            src: src,
            tokens: tokens,
            productions: get_productions(),
            table: get_table(),
            stack: vec!["EOF".to_string(), "Re".to_string()],
        }
    }

    fn parse_focus(&self) -> Option<String> {
        assert!(self.stack.len() != 0, "OVERFLOW {:?}", self);
        self.stack.get(self.stack.len() - 1)
            .map(|s| s.clone())
    }

    pub fn parse(&mut self) -> bool {
        loop {
            let ref token = self.tokens[self.index];
            let parse_focus = self.parse_focus().expect("Something went wrong");

            println!("pfocus {:?} {:?} stack {:?}", parse_focus,
                    token, self.stack);

            if parse_focus == "EOF" && token.category == "EOF" {
                return true;
            } else if is_terminal(&parse_focus) {
                if *parse_focus == token.category {
                    self.stack.pop().unwrap();
                    self.index += 1;
                } else {
                    panic!(
                        "ERROR: no entry found in table. parse focus {:?}, token {:?}, stack {:?}",
                        parse_focus, token, self.stack)
                }
            } else {
                let prod_number = self.table.get(&(parse_focus, token.category.clone()))
                    .expect("ERROR: expanding parse_focus");

                let prod = self.productions.get(*prod_number)
                    .expect("ERROR: expanding parse_focus");

                self.stack.pop().unwrap();
                for s in prod.to.iter().rev() {
                    if s != "Lambda" {
                        self.stack.push(s.clone());
                    }
                }
            }
        }
    }
}

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

    #[test]
    fn parse_test() {

        let cases = vec!["a",
                         "(a)",
                         "(aa)",
                         "a*b",
                         "(a*)b",
                         "(a)*b",
                         "a|(cde)*a+",
                         "((((aaa))))"];

        let expect = vec![true, true, true, true, true, true, true, true];

        for (c, e) in cases.iter().zip(expect.iter()) {
            println!("\nCase {:?}\n", c);
            let mut p = Parser::new(c.to_string());
            assert_eq!(p.parse(), *e, "In {:?}", c);
            //p.print();
        }
    }
}
<commit_msg>cargo fmt<commit_after>use std::collections::{HashSet, HashMap};
use std::cell::{Cell, RefCell};

use regexp::{Token, lex};

pub fn re2(search: String, into: &'static str) -> Result<(), ()> {
    Ok(())
}

#[derive(Debug)]
struct Production {
    from: String,
    to: Vec<String>,
}

impl Production {
    pub fn new<T: Into<String>>(from: T, to: Vec<T>) -> Production {

        let mut to_arr = vec![];
        for x in to {
            to_arr.push(x.into())
        }
        Production {
            from: from.into(),
            to: to_arr,
        }
    }
}

fn get_productions() -> Vec<Production> {
    let prods = vec![Production::new("Re", vec!["Lit", "Ops"]),
                     Production::new("Re", vec!["(", "Re", ")", "Ops"]),

                     Production::new("Ops", vec!["*", "ReL"]),
                     Production::new("Ops", vec!["+", "ReL"]),
                     Production::new("Ops", vec!["|", "Re"]),
                     Production::new("Ops", vec!["Re"]),
                     Production::new("Ops", vec!["Lambda"]),

                     Production::new("ReL", vec!["Re"]),
                     Production::new("ReL", vec!["Lambda"])];

    prods
}

fn get_table() -> HashMap<(String, String), usize> {
    let entries = [(("Re", "Lit"), 0),
                   (("Re", "("), 1),

                   (("Ops", "*"), 2),
                   (("Ops", "+"), 3),
                   (("Ops", "|"), 4),
                   (("Ops", "Lit"), 5),
                   (("Ops", "("), 5),
                   (("Ops", "EOF"), 6),
                   (("Ops", ")"), 6),
                   (("Ops", "Lambda"), 6),

                   (("ReL", "Lit"), 7),
                   (("ReL", "("), 7),
                   (("ReL", "EOF"), 8),
                   (("ReL", ")"), 8),
                   (("ReL", "Lambda"), 8)];

    let mut table = HashMap::new();
    for &((non_terminal, token_cat), value) in entries.iter() {
        table.insert((non_terminal.to_string(), token_cat.to_string()), value);
    }

    //table.insert(("Re", "Lit"), 0);
    //table.insert(("Re", "("), 1);

    //table.insert(("Ops", "*"), 2);
    //table.insert(("Ops", "+"), 3);
    //table.insert(("Ops", "|"), 4);
    //table.insert(("Ops", "Lit"), 5);
    //table.insert(("Ops", "("), 5);
    //table.insert(("Ops", "eof"), 6);
    //table.insert(("Ops", ")"), 6);
    //table.insert(("Ops", "Lambda"), 6);

    //table.insert(("ReL", "Lit"), 7);
    //table.insert(("ReL", "("), 7);
    //table.insert(("ReL", "eof"), 8);
    //table.insert(("ReL", ")"), 8);
    //table.insert(("ReL", "Lambda"), 8);

    table
}

fn is_terminal(s: &String) -> bool {
    let t = vec!["Lit", "(", ")", "*", "+", "|", "EOF", "Lambda"];

    let terminals: HashSet<String> = t.iter().cloned().map(|s| s.to_string()).collect();
    terminals.contains(s)
}

#[derive(Debug)]
struct Parser {
    pub index: usize,
    pub src: String,
    pub tokens: Vec<Token>,
    pub productions: Vec<Production>,
    pub table: HashMap<(String, String), usize>,
    stack: Vec<String>,
}

impl Parser {
    pub fn new(src: String) -> Parser {
        let tokens = lex(src.clone());
        //let root = Node::new_nt("Re");
        Parser {
            index: 0,
            src: src,
            tokens: tokens,
            productions: get_productions(),
            table: get_table(),
            stack: vec!["EOF".to_string(), "Re".to_string()],
        }
    }

    fn parse_focus(&self) -> Option<String> {
        assert!(self.stack.len() != 0, "OVERFLOW {:?}", self);
        self.stack.get(self.stack.len() - 1).map(|s| s.clone())
    }

    pub fn parse(&mut self) -> bool {
        loop {
            let ref token = self.tokens[self.index];
            let parse_focus = self.parse_focus().expect("Something went wrong");

            println!("pfocus {:?} {:?} stack {:?}",
                     parse_focus,
                     token,
                     self.stack);

            if parse_focus == "EOF" && token.category == "EOF" {
                return true;
            } else if is_terminal(&parse_focus) {
                if *parse_focus == token.category {
                    self.stack.pop().unwrap();
                    self.index += 1;
                } else {
                    panic!("ERROR: no entry found in table. parse focus {:?}, token {:?}, stack {:?}",
                           parse_focus,
                           token,
                           self.stack)
                }
            } else {
                let prod_number = self.table
                    .get(&(parse_focus, token.category.clone()))
                    .expect("ERROR: expanding parse_focus");

                let prod = self.productions
                    .get(*prod_number)
                    .expect("ERROR: expanding parse_focus");

                self.stack.pop().unwrap();
                for s in prod.to.iter().rev() {
                    if s != "Lambda" {
                        self.stack.push(s.clone());
                    }
                }
            }
        }
    }
}

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

    #[test]
    fn parse_test() {

        let cases = vec!["a",
                         "(a)",
                         "(aa)",
                         "a*b",
                         "(a*)b",
                         "(a)*b",
                         "a|(cde)*a+",
                         "((((aaa))))"];

        let expect = vec![true, true, true, true, true, true, true, true];

        for (c, e) in cases.iter().zip(expect.iter()) {
            println!("\nCase {:?}\n", c);
            let mut p = Parser::new(c.to_string());
            assert_eq!(p.parse(), *e, "In {:?}", c);
            //p.print();
        }
    }
}
<|endoftext|>


<commit_before>extern crate pkg_config;

use std::env;
use std::fs::{self, File};
use std::io::ErrorKind;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(n) => n,
        Err(e) => fail(&format!("\n{} failed with {}\n", stringify!($e), e)),
    })
}

fn main() {
    register_dep("SSH2");
    register_dep("OPENSSL");

    if env::var("LIBSSH2_SYS_USE_PKG_CONFIG").is_ok() {
        if pkg_config::find_library("libgit2").is_ok() {
            return
        }
    }

    let mut cflags = env::var("CFLAGS").unwrap_or(String::new());
    let target = env::var("TARGET").unwrap();
    let mingw = target.contains("windows-gnu");
    let msvc = target.contains("msvc");

    if msvc {
        // libgit2 passes the /GL flag to enable whole program optimization, but
        // this requires that the /LTCG flag is passed to the linker later on,
        // and currently the compiler does not do that, so we disable whole
        // program optimization entirely.
        cflags.push_str(" /GL-");
    } else {
        cflags.push_str(" -ffunction-sections -fdata-sections");

        if target.contains("i686") {
            cflags.push_str(" -m32");
        } else if target.contains("x86_64") {
            cflags.push_str(" -m64");
        }
        if !target.contains("i686") {
            cflags.push_str(" -fPIC");
        }
    }

    // libgit2 uses pkg-config to discover libssh2, but this doesn't work on
    // windows as libssh2 doesn't come with a libssh2.pc file in that install.
    // As a result we just manually turn on SSH support in libgit2 (a little
    // jankily) here...
    if mingw {
        cflags.push_str(" -DGIT_SSH");
    } else if msvc {
        cflags.push_str(" /DGIT_SSH");
    }
    if let Ok(libssh2_include) = env::var("DEP_SSH2_INCLUDE") {
        if mingw {
            cflags.push_str(&format!(" -I{}", libssh2_include));
        } else if msvc {
            cflags.push_str(&format!(" /I{}", libssh2_include));
        }
    }

    let src = PathBuf::from(&env::var("CARGO_MANIFEST_DIR").unwrap());
    let dst = PathBuf::from(&env::var("OUT_DIR").unwrap());
    let _ = fs::create_dir(&dst.join("build"));

    let mut cmd = Command::new("cmake");
    cmd.arg(&src.join("libgit2"))
       .current_dir(&dst.join("build"));
    if mingw {
        cmd.arg("-G").arg("Unix Makefiles");
    } else if msvc {
        // If we don't pass this unfortunately cmake produces 32-bit builds
        cmd.arg("-G").arg("Visual Studio 12 2013 Win64");

        // Currently liblibc links to msvcrt which apparently is a dynamic CRT,
        // so we need to turn this off to get it to link right.
        cmd.arg("-DSTATIC_CRT=OFF");
    }
    let profile = match &env::var("PROFILE").unwrap()[..] {
        "bench" | "release" => "Release",
        _ if msvc => "Release", // currently we need to always use the same CRT
        _ => "Debug",
    };
    run(cmd.arg("-DBUILD_SHARED_LIBS=OFF")
           .arg("-DBUILD_CLAR=OFF")
           .arg(&format!("-DCMAKE_BUILD_TYPE={}", profile))
           .arg(&format!("-DCMAKE_INSTALL_PREFIX={}", dst.display()))
           .arg(&format!("-DCMAKE_C_FLAGS={}", cflags)), "cmake");

    let flags = dst.join("build/CMakeFiles/git2.dir/flags.make");
    let mut contents = String::new();

    // Make sure libssh2 was detected on unix systems, because it definitely
    // should have been!
    if !msvc {
        t!(t!(File::open(flags)).read_to_string(&mut contents));
        if !contents.contains("-DGIT_SSH") {
            fail("libgit2 failed to find libssh2, and SSH support is required");
        }
    }

    run(Command::new("cmake")
                .arg("--build").arg(".")
                .arg("--target").arg("install")
                .arg("--config").arg(profile)
                .current_dir(&dst.join("build")), "cmake");

    println!("cargo:root={}", dst.display());
    if mingw || target.contains("windows") {
        println!("cargo:rustc-flags=-l winhttp -l rpcrt4 -l ole32 \
                                    -l static=git2");
        println!("cargo:rustc-link-search=native={}/lib", dst.display());
        return
    }

    if env::var("HOST") == env::var("TARGET") {
        prepend("PKG_CONFIG_PATH", dst.join("lib/pkgconfig"));
        if pkg_config::Config::new().statik(true).find("libgit2").is_ok() {
            return
        }
    }

    println!("cargo:rustc-flags=-l static=git2");
    println!("cargo:rustc-flags=-L {}", dst.join("lib").display());
    if target.contains("apple") {
        println!("cargo:rustc-flags=-l iconv");
    }
}

fn run(cmd: &mut Command, program: &str) {
    println!("running: {:?}", cmd);
    let status = match cmd.status() {
        Ok(status) => status,
        Err(ref e) if e.kind() == ErrorKind::NotFound => {
            fail(&format!("failed to execute command: {}\nis `{}` not installed?",
                          e, program));
        }
        Err(e) => fail(&format!("failed to execute command: {}", e)),
    };
    if !status.success() {
        fail(&format!("command did not execute successfully, got: {}", status));
    }
}

fn register_dep(dep: &str) {
    match env::var(&format!("DEP_{}_ROOT", dep)) {
        Ok(s) => {
            prepend("CMAKE_PREFIX_PATH", PathBuf::from(&s));
            prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig"));
        }
        Err(..) => {}
    }
}

fn prepend(var: &str, val: PathBuf) {
    let prefix = env::var(var).unwrap_or(String::new());
    let mut v = vec![val];
    v.extend(env::split_paths(&prefix));
    env::set_var(var, &env::join_paths(v).unwrap());
}

fn fail(s: &str) -> ! {
    panic!("\n{}\n\nbuild script failed, must exit now", s)
}
<commit_msg>Add crypt32 to windows and switch syntax a bit<commit_after>extern crate pkg_config;

use std::env;
use std::fs::{self, File};
use std::io::ErrorKind;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(n) => n,
        Err(e) => fail(&format!("\n{} failed with {}\n", stringify!($e), e)),
    })
}

fn main() {
    register_dep("SSH2");
    register_dep("OPENSSL");

    if env::var("LIBSSH2_SYS_USE_PKG_CONFIG").is_ok() {
        if pkg_config::find_library("libgit2").is_ok() {
            return
        }
    }

    let mut cflags = env::var("CFLAGS").unwrap_or(String::new());
    let target = env::var("TARGET").unwrap();
    let mingw = target.contains("windows-gnu");
    let msvc = target.contains("msvc");

    if msvc {
        // libgit2 passes the /GL flag to enable whole program optimization, but
        // this requires that the /LTCG flag is passed to the linker later on,
        // and currently the compiler does not do that, so we disable whole
        // program optimization entirely.
        cflags.push_str(" /GL-");
    } else {
        cflags.push_str(" -ffunction-sections -fdata-sections");

        if target.contains("i686") {
            cflags.push_str(" -m32");
        } else if target.contains("x86_64") {
            cflags.push_str(" -m64");
        }
        if !target.contains("i686") {
            cflags.push_str(" -fPIC");
        }
    }

    // libgit2 uses pkg-config to discover libssh2, but this doesn't work on
    // windows as libssh2 doesn't come with a libssh2.pc file in that install.
    // As a result we just manually turn on SSH support in libgit2 (a little
    // jankily) here...
    if mingw {
        cflags.push_str(" -DGIT_SSH");
    } else if msvc {
        cflags.push_str(" /DGIT_SSH");
    }
    if let Ok(libssh2_include) = env::var("DEP_SSH2_INCLUDE") {
        if mingw {
            cflags.push_str(&format!(" -I{}", libssh2_include));
        } else if msvc {
            cflags.push_str(&format!(" /I{}", libssh2_include));
        }
    }

    let src = PathBuf::from(&env::var("CARGO_MANIFEST_DIR").unwrap());
    let dst = PathBuf::from(&env::var("OUT_DIR").unwrap());
    let _ = fs::create_dir(&dst.join("build"));

    let mut cmd = Command::new("cmake");
    cmd.arg(&src.join("libgit2"))
       .current_dir(&dst.join("build"));
    if mingw {
        cmd.arg("-G").arg("Unix Makefiles");
    } else if msvc {
        // If we don't pass this unfortunately cmake produces 32-bit builds
        cmd.arg("-G").arg("Visual Studio 12 2013 Win64");

        // Currently liblibc links to msvcrt which apparently is a dynamic CRT,
        // so we need to turn this off to get it to link right.
        cmd.arg("-DSTATIC_CRT=OFF");
    }
    let profile = match &env::var("PROFILE").unwrap()[..] {
        "bench" | "release" => "Release",
        _ if msvc => "Release", // currently we need to always use the same CRT
        _ => "Debug",
    };
    run(cmd.arg("-DBUILD_SHARED_LIBS=OFF")
           .arg("-DBUILD_CLAR=OFF")
           .arg(&format!("-DCMAKE_BUILD_TYPE={}", profile))
           .arg(&format!("-DCMAKE_INSTALL_PREFIX={}", dst.display()))
           .arg(&format!("-DCMAKE_C_FLAGS={}", cflags)), "cmake");

    let flags = dst.join("build/CMakeFiles/git2.dir/flags.make");
    let mut contents = String::new();

    // Make sure libssh2 was detected on unix systems, because it definitely
    // should have been!
    if !msvc {
        t!(t!(File::open(flags)).read_to_string(&mut contents));
        if !contents.contains("-DGIT_SSH") {
            fail("libgit2 failed to find libssh2, and SSH support is required");
        }
    }

    run(Command::new("cmake")
                .arg("--build").arg(".")
                .arg("--target").arg("install")
                .arg("--config").arg(profile)
                .current_dir(&dst.join("build")), "cmake");

    println!("cargo:root={}", dst.display());
    if target.contains("windows") {
        println!("cargo:rustc-link-lib=winhttp");
        println!("cargo:rustc-link-lib=rpcrt4");
        println!("cargo:rustc-link-lib=ole32");
        println!("cargo:rustc-link-lib=crypt32");
        println!("cargo:rustc-link-lib=static=git2");
        println!("cargo:rustc-link-search=native={}/lib", dst.display());
        return
    }

    if env::var("HOST") == env::var("TARGET") {
        prepend("PKG_CONFIG_PATH", dst.join("lib/pkgconfig"));
        if pkg_config::Config::new().statik(true).find("libgit2").is_ok() {
            return
        }
    }

    println!("cargo:rustc-link-lib=static=git2");
    println!("cargo:rustc-link-search=native={}", dst.join("lib").display());
    if target.contains("apple") {
        println!("cargo:rustc-link-lib=iconv");
    }
}

fn run(cmd: &mut Command, program: &str) {
    println!("running: {:?}", cmd);
    let status = match cmd.status() {
        Ok(status) => status,
        Err(ref e) if e.kind() == ErrorKind::NotFound => {
            fail(&format!("failed to execute command: {}\nis `{}` not installed?",
                          e, program));
        }
        Err(e) => fail(&format!("failed to execute command: {}", e)),
    };
    if !status.success() {
        fail(&format!("command did not execute successfully, got: {}", status));
    }
}

fn register_dep(dep: &str) {
    match env::var(&format!("DEP_{}_ROOT", dep)) {
        Ok(s) => {
            prepend("CMAKE_PREFIX_PATH", PathBuf::from(&s));
            prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig"));
        }
        Err(..) => {}
    }
}

fn prepend(var: &str, val: PathBuf) {
    let prefix = env::var(var).unwrap_or(String::new());
    let mut v = vec![val];
    v.extend(env::split_paths(&prefix));
    env::set_var(var, &env::join_paths(v).unwrap());
}

fn fail(s: &str) -> ! {
    panic!("\n{}\n\nbuild script failed, must exit now", s)
}
<|endoftext|>


<commit_before>use std::cmp::{max, min};
use std::fmt;
use std::ops;

#[derive(Debug, Clone, PartialEq)]
struct Board {
    cells: Vec<Vec<Option<u32>>>,
}

impl Board {
    fn new(initial_board: Vec<Vec<u32>>) -> Self {
        let b = initial_board
            .iter()
            .map(|r| {
                r.iter()
                    .map(|c| if *c == u32::MAX { None } else { Some(*c) })
                    .collect()
            })
            .collect();

        Board { cells: b }
    }

    fn height(&self) -> usize {
        self.cells.len()
    }

    fn width(&self) -> usize {
        self.cells[0].len()
    }
}
impl ops::Index<(usize, usize)> for Board {
    type Output = Option<u32>;

    fn index(&self, (y, x): (usize, usize)) -> &Self::Output {
        &self.cells[y][x]
    }
}
impl ops::IndexMut<(usize, usize)> for Board {
    /// Returns a mutable reference to an cell for a given 'x' 'y' coordinates
    fn index_mut(&mut self, (y, x): (usize, usize)) -> &mut Option<u32> {
        &mut self.cells[y][x]
    }
}

impl fmt::Display for Board {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let output: Vec<String> = self
            .cells
            .iter()
            .map(|r| {
                let mut row = String::default();

                r.iter().for_each(|c| match c {
                    None => row.push_str(format!("{:>2} ", " ").as_ref()),
                    Some(c) if c == &0 => row.push_str(format!("{:>2} ", ".").as_ref()),
                    Some(c) => row.push_str(format!("{:>2} ", c).as_ref()),
                });
                row
            })
            .collect();

        write!(f, "{}", output.join("\n"))
    }
}

/// Structure for holding puzzle related information
/// * `board`: the state of the board
/// * `fixed`: all the numbers which were given at puzzle setup,
/// aka all the numbers which cannot be changed during solving the puzzle
/// * `start`: position of the first number (1)
#[derive(Clone, Debug)]
struct Puzzle {
    board: Board,
    fixed: Vec<u32>,
    start: (usize, usize),
}

impl Puzzle {
    /// Creates a new puzzle
    /// * `initial_board` contains the  layout and the startin position.
    ///
    /// - Simple numbers in the `initial_board` are considered as "fixed",
    /// aka the solving does not change them
    ///
    /// - As the board can be non-rectangular, all cells which are invalid or cannot be used
    /// are marked with u32::MAX in the `initial_board`
    fn new(initial_board: Vec<Vec<u32>>) -> Self {
        let mut s: (usize, usize) = (0, 0);
        let mut f = initial_board
            .iter()
            .enumerate()
            .flat_map(|(y, r)| r.iter().enumerate().map(move |(x, c)| (y, x, *c)))
            .filter(|(_, _, c)| (1..u32::MAX).contains(c))
            .fold(Vec::new(), |mut fixed, (y, x, c)| {
                fixed.push(c);
                if c == 1 {
                    // store the position of the start
                    s = (y, x)
                };
                fixed
            });

        f.sort_unstable();

        Puzzle {
            board: Board::new(initial_board),
            fixed: f,
            start: s,
        }
    }

    pub fn print_board(&self) {
        println!("{}", self.board);
    }

    fn solver(&mut self, current: (usize, usize), n: &u32, mut next: usize) -> bool {
        // reached the last number, solving successful
        if n > self.fixed.last().unwrap() {
            return true;
        }

        // check for exit conditions
        match self.board[current] {
            // cell outside of the board
            None => return false,

            //cell is already has a number in it
            Some(c) if c != 0 && c != *n => return false,

            //cell is empty, but the to be placed number is already matching the next fixed number
            Some(c) if c == 0 && self.fixed[next] == *n => return false,

            // continue
            _ => (),
        }

        let mut backup: u32 = 0;
        if self.board[current] == Some(*n) {
            backup = *n;
            next += 1;
        }

        self.board[current] = Some(*n);

        for y in (max(current.0, 1) - 1)..=min(current.0 + 1, self.board.height() - 1) {
            for x in (max(current.1, 1) - 1)..=min(current.1 + 1, self.board.width() - 1) {
                if self.solver((y, x), &(n + 1), next) {
                    return true;
                }
            }
        }

        // unsuccessful branch, restore original value
        self.board[current] = Some(backup);
        false
    }

    pub fn solve(&mut self) {
        let start = self.start;
        self.solver(start, &1, 0);
    }
}

fn main() {
    let input = vec![
        vec![0, 33, 35, 0, 0, u32::MAX, u32::MAX, u32::MAX],
        vec![0, 0, 24, 22, 0, u32::MAX, u32::MAX, u32::MAX],
        vec![0, 0, 0, 21, 0, 0, u32::MAX, u32::MAX],
        vec![0, 26, 0, 13, 40, 11, u32::MAX, u32::MAX],
        vec![27, 0, 0, 0, 9, 0, 1, u32::MAX],
        vec![u32::MAX, u32::MAX, 0, 0, 18, 0, 0, u32::MAX],
        vec![u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 7, 0, 0],
        vec![
            u32::MAX,
            u32::MAX,
            u32::MAX,
            u32::MAX,
            u32::MAX,
            u32::MAX,
            5,
            0,
        ],
    ];

    let mut p = Puzzle::new(input);
    p.print_board();
    p.solve();
    println!("\nSolution:");
    p.print_board();
}

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

    #[test]
    fn test_solver() {
        let input = vec![vec![0, 1], vec![4, 0]];
        let mut p = Puzzle::new(input);
        p.solve();
        assert_eq!(p.board, Board::new(vec![vec![2, 1], vec![4, 3]]));

        // test disabled cells
        let input = vec![vec![u32::MAX, 1, 0], vec![5, 0, 0]];
        let mut p = Puzzle::new(input);
        p.solve();
        assert_eq!(
            p.board,
            Board::new(vec![vec![u32::MAX, 1, 2], vec![5, 4, 3]])
        );
    }
}
<commit_msg>Update doc comments<commit_after>use std::cmp::{max, min};
use std::fmt;
use std::ops;

#[derive(Debug, Clone, PartialEq)]
struct Board {
    cells: Vec<Vec<Option<u32>>>,
}

impl Board {
    fn new(initial_board: Vec<Vec<u32>>) -> Self {
        let b = initial_board
            .iter()
            .map(|r| {
                r.iter()
                    .map(|c| if *c == u32::MAX { None } else { Some(*c) })
                    .collect()
            })
            .collect();

        Board { cells: b }
    }

    fn height(&self) -> usize {
        self.cells.len()
    }

    fn width(&self) -> usize {
        self.cells[0].len()
    }
}
impl ops::Index<(usize, usize)> for Board {
    type Output = Option<u32>;

    fn index(&self, (y, x): (usize, usize)) -> &Self::Output {
        &self.cells[y][x]
    }
}
impl ops::IndexMut<(usize, usize)> for Board {
    /// Returns a mutable reference to an cell for a given 'x' 'y' coordinates
    fn index_mut(&mut self, (y, x): (usize, usize)) -> &mut Option<u32> {
        &mut self.cells[y][x]
    }
}

impl fmt::Display for Board {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let output: Vec<String> = self
            .cells
            .iter()
            .map(|r| {
                let mut row = String::default();

                r.iter().for_each(|c| match c {
                    None => row.push_str(format!("{:>2} ", " ").as_ref()),
                    Some(c) if c == &0 => row.push_str(format!("{:>2} ", ".").as_ref()),
                    Some(c) => row.push_str(format!("{:>2} ", c).as_ref()),
                });
                row
            })
            .collect();

        write!(f, "{}", output.join("\n"))
    }
}

/// Structure for holding puzzle related information.
#[derive(Clone, Debug)]
struct Puzzle {
    /// The state of the board.
    board: Board,

    /// All the numbers which were given at puzzle setup:
    /// the numbers which cannot be changed during solving the puzzle.
    fixed: Vec<u32>,

    /// Position of the first number (1).
    start: (usize, usize),
}

impl Puzzle {
    /// Creates a new puzzle
    /// * `initial_board` contains the  layout and the startin position.
    ///
    /// - Simple numbers in the `initial_board` are considered as "fixed",
    /// aka the solving does not change them
    ///
    /// - As the board can be non-rectangular, all cells which are invalid or cannot be used
    /// are marked with u32::MAX in the `initial_board`
    fn new(initial_board: Vec<Vec<u32>>) -> Self {
        let mut s: (usize, usize) = (0, 0);
        let mut f = initial_board
            .iter()
            .enumerate()
            .flat_map(|(y, r)| r.iter().enumerate().map(move |(x, c)| (y, x, *c)))
            .filter(|(_, _, c)| (1..u32::MAX).contains(c))
            .fold(Vec::new(), |mut fixed, (y, x, c)| {
                fixed.push(c);
                if c == 1 {
                    // store the position of the start
                    s = (y, x)
                };
                fixed
            });

        f.sort_unstable();

        Puzzle {
            board: Board::new(initial_board),
            fixed: f,
            start: s,
        }
    }

    pub fn print_board(&self) {
        println!("{}", self.board);
    }

    fn solver(&mut self, current: (usize, usize), n: &u32, mut next: usize) -> bool {
        // reached the last number, solving successful
        if n > self.fixed.last().unwrap() {
            return true;
        }

        // check for exit conditions
        match self.board[current] {
            // cell outside of the board
            None => return false,

            //cell is already has a number in it
            Some(c) if c != 0 && c != *n => return false,

            //cell is empty, but the to be placed number is already matching the next fixed number
            Some(c) if c == 0 && self.fixed[next] == *n => return false,

            // continue
            _ => (),
        }

        let mut backup: u32 = 0;
        if self.board[current] == Some(*n) {
            backup = *n;
            next += 1;
        }

        self.board[current] = Some(*n);

        for y in (max(current.0, 1) - 1)..=min(current.0 + 1, self.board.height() - 1) {
            for x in (max(current.1, 1) - 1)..=min(current.1 + 1, self.board.width() - 1) {
                if self.solver((y, x), &(n + 1), next) {
                    return true;
                }
            }
        }

        // unsuccessful branch, restore original value
        self.board[current] = Some(backup);
        false
    }

    pub fn solve(&mut self) {
        let start = self.start;
        self.solver(start, &1, 0);
    }
}

fn main() {
    let input = vec![
        vec![0, 33, 35, 0, 0, u32::MAX, u32::MAX, u32::MAX],
        vec![0, 0, 24, 22, 0, u32::MAX, u32::MAX, u32::MAX],
        vec![0, 0, 0, 21, 0, 0, u32::MAX, u32::MAX],
        vec![0, 26, 0, 13, 40, 11, u32::MAX, u32::MAX],
        vec![27, 0, 0, 0, 9, 0, 1, u32::MAX],
        vec![u32::MAX, u32::MAX, 0, 0, 18, 0, 0, u32::MAX],
        vec![u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 7, 0, 0],
        vec![
            u32::MAX,
            u32::MAX,
            u32::MAX,
            u32::MAX,
            u32::MAX,
            u32::MAX,
            5,
            0,
        ],
    ];

    let mut p = Puzzle::new(input);
    p.print_board();
    p.solve();
    println!("\nSolution:");
    p.print_board();
}

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

    #[test]
    fn test_solver() {
        let input = vec![vec![0, 1], vec![4, 0]];
        let mut p = Puzzle::new(input);
        p.solve();
        assert_eq!(p.board, Board::new(vec![vec![2, 1], vec![4, 3]]));

        // test disabled cells
        let input = vec![vec![u32::MAX, 1, 0], vec![5, 0, 0]];
        let mut p = Puzzle::new(input);
        p.solve();
        assert_eq!(
            p.board,
            Board::new(vec![vec![u32::MAX, 1, 2], vec![5, 4, 3]])
        );
    }
}
<|endoftext|>


<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<T> {
    count: usize,
    states: Vec<State<T>>,
}

impl<T: 'static + FromStr> Merge<T> {
    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<T: 'static + PartialOrd + Copy> Iterator for Merge<T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        let count = self.count;
        let states = &mut self.states;
        for i in 0..count {
            let state = &mut states[i];
            if state.1.is_none() {
                state.1 = state.0.next();
            }
        }
        let mut min_index: Option<usize> = None;
        for i in 0..count {
            if let Some(val) = states[i].1 {
                if let Some(m) = min_index {
                    let min = states[m].1.unwrap();
                    if val < min {
                        min_index.replace(i);
                    }
                } else {
                    min_index.replace(i);
                }
            }
        }
        if let Some(m) = min_index {
            return states[m].1.take();
        }
        return None;
    }
}

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<T: PartialOrd>(
        iter1: &mut impl Iterator<Item = T>,
        iter2: &mut impl Iterator<Item = T>,
    ) -> 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>Fix 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> {
    count: usize,
    states: Vec<State<T>>,
}

impl<T: 'static + FromStr> Merge<T> {
    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<T: 'static + PartialOrd + Copy> Iterator for Merge<T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        let count = self.count;
        let states = &mut self.states;
        for i in 0..count {
            let state = &mut states[i];
            if state.1.is_none() {
                state.1 = state.0.next();
            }
        }
        let mut min_index: Option<usize> = None;
        for i in 0..count {
            if let Some(val) = states[i].1 {
                if let Some(m) = min_index {
                    let min = states[m].1.unwrap();
                    if val < min {
                        min_index.replace(i);
                    }
                } else {
                    min_index.replace(i);
                }
            }
        }
        if let Some(m) = min_index {
            return states[m].1.take();
        }
        return None;
    }
}

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<T: 'static + FromStr + PartialOrd + Copy>(filename: &str) -> (impl Iterator<Item = T>, impl Iterator<Item = T>) {
        let result = Merge::new(filename);
        let output = get_output(filename).unwrap();
        (result, output)
    }

    fn assert_iterator<T: PartialEq>(
        iter1: &mut impl Iterator<Item = T>,
        iter2: &mut impl Iterator<Item = T>,
    ) -> 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::<u32>(filename);
        assert!(assert_iterator(&mut result, &mut output));
    }

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

    #[test]
    fn test_zero_merge() {
        let filename = "../data/zero.txt";
        let (mut result, mut output) = merge::<u32>(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::<u32>(filename);
        assert!(!assert_iterator(&mut result, &mut output));
    }
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Gaussian_elimination
#![allow(unused_variables)]
#![allow(dead_code)]

struct Matrix<'a, T:'a> {
	m : &'a mut Vec<T>,
	n : usize
}

struct Idx(usize, usize);

impl<'a, T:'a> Matrix<'a, T> {
	fn new<'b> (_m : &'b mut Vec<T>, _n : usize) -> Matrix<'b, T> {
		Matrix{m : /*&mut*/ _m, n : _n}
	}

	fn val(&self, idx : Idx) -> & T
	{
		& self.m[idx.0 + idx.1 * self.n]
	}

	// fn val_mut<'b>(&'b mut self, idx : Idx) -> &'b mut T
	// {
	// 	let r : &mut T =	& mut (*self.m)[idx.0 + idx.1 * self.n];
	// 	r
	// }

	fn set(&mut self, idx : Idx, v : T)
	{
		self.m[idx.0 + idx.1 * self.n] = v;
	}

	fn get_row_slice(&self, row: usize) -> &[T]
	{
	  & self.m[row * self.n .. row * self.n + self.n ]
	}
}

struct MatrixRowIter<'a, T:'a> {
	m : &'a Matrix<'a, T>,
	row : usize,
	col : usize,
	used: &'a Vec<bool>
}

impl<'a, T> MatrixRowIter<'a, T> {
	fn new (_m : &'a Matrix<'a, T>, _used: &'a mut Vec<bool>, _col : usize) -> MatrixRowIter<'a, T> {
		MatrixRowIter{m : _m, row : 0, col : _col, used : _used }
	}

}

impl<'a, T:Copy> Iterator for MatrixRowIter<'a, T> {
    type Item = (T, usize);
    fn next(&mut self) -> Option<(T, usize)> {
    	loop {
	    	if self.row >= self.m.n {
	    	  return None
	    	}
	    	if !self.used[self.row] {
	    		break;
	    	}
    		self.row += 1;
    	}

    	let v = *self.m.val(Idx(self.col, self.row));
    	let ret = self.row;
    	self.row += 1;
      Some((v, ret))
    }
}

fn main() {

	let mut v : Vec<f32> = vec![
		1.00, 0.00, 0.00,  0.00,  0.00, 0.00,
		1.00, 0.63, 0.39,  0.25,  0.16, 0.10,
		1.00, 1.26, 1.58,  1.98,  2.49, 3.13,
		1.00, 1.88, 3.55,  6.70, 12.62, 230.80,
		1.00, 2.51, 6.32, 15.88, 39.90, 100.28,
		1.00, 3.14, 9.87, 31.01, 97.41, 306.02];

	let mat = Matrix::new(&mut v, 6);

	let zero:f32 = 0.0;
	let mut r = Vec::new();
	let mut used: Vec<bool> = vec![false; mat.n];

	for i in 0..mat.n {

		let max;
		{
			let mat_iter = MatrixRowIter::new(&mat, &mut used, i);

			max = mat_iter
						.inspect(|&item| println!("{} {}", item.0, item.1) )
						.fold((0.0, -1),
							|max, item| if item.0.abs() > max.0 { item } else { max } )
						;
		}

		used[max.1] = true;
		println!("max {} {}", max.0, max.1);
		println!("=======");

		r.extend(mat.get_row_slice(max.1).iter());
	}

	let mut mat_out = Matrix::new(&mut r, mat.n);
	for i in 0..mat_out.n {
		for j in 0..mat_out.n {
			print!("{} ", mat_out.val(Idx(j, i)));
		}
		println!("  ");
	}

	let n= mat_out.n;
	for dia in 0..n {
		for row in dia+1..n {
			//let tmp = *mat_out.val(Idx(dia, row)) / *mat_out.val(Idx(dia, dia));
			for col in dia+1..n {
				//(*mat_out.val(Idx(col, row))) -= tmp;// * *mat_out.val(Idx(col, dia));
				//mat_out.val_mut(Idx(dia, row)) = 0.0;
				//let ref mut  rr : &mut &f32 = mat_out.val_mut(Idx(dia, row));
//				let rr : & mut f32   = &mut mat_out.val_mut(Idx(dia, row));
	//			println!("{}", rr);
				//*mat_out.val_mut(Idx(dia, row)) = 0.0;
				mat_out.set(Idx(dia, row), &zero);
				//*rr = 0.0;
			}
		}
	}

}
<commit_msg>maybe trait Copy help me ?<commit_after>// http://rosettacode.org/wiki/Gaussian_elimination
#![allow(unused_variables)]
#![allow(dead_code)]

struct Matrix<'a, T:'a> where T: Copy {
	m : &'a mut Vec<T>,
	n : usize
}

struct Idx(usize, usize);

impl<'a, T:'a> Matrix<'a, T> where T: Copy {
	fn new<'b> (_m : &'b mut Vec<T>, _n : usize) -> Matrix<'b, T> {
		Matrix{m : /*&mut*/ _m, n : _n}
	}

	fn val(&self, idx : Idx) -> & T
	{
		& self.m[idx.0 + idx.1 * self.n]
	}

	// fn val_mut<'b>(&'b mut self, idx : Idx) -> &'b mut T
	// {
	// 	let r : &mut T =	& mut (*self.m)[idx.0 + idx.1 * self.n];
	// 	r
	// }

	fn set(&mut self, idx : Idx, v : T)
	{
		self.m[idx.0 + idx.1 * self.n] = v;
	}

	fn get_row_slice(&self, row: usize) -> &[T]
	{
	  & self.m[row * self.n .. row * self.n + self.n ]
	}
}

struct MatrixRowIter<'a, T:'a> where T: Copy {
	m : &'a Matrix<'a, T>,
	row : usize,
	col : usize,
	used: &'a Vec<bool>
}

impl<'a, T> MatrixRowIter<'a, T> where T: Copy {
	fn new (_m : &'a Matrix<'a, T>, _used: &'a mut Vec<bool>, _col : usize) -> MatrixRowIter<'a, T> {
		MatrixRowIter{m : _m, row : 0, col : _col, used : _used }
	}

}

impl<'a, T> Iterator for MatrixRowIter<'a, T> where T: Copy {
    type Item = (T, usize);
    fn next(&mut self) -> Option<(T, usize)> {
    	loop {
	    	if self.row >= self.m.n {
	    	  return None
	    	}
	    	if !self.used[self.row] {
	    		break;
	    	}
    		self.row += 1;
    	}

    	let v = *self.m.val(Idx(self.col, self.row));
    	let ret = self.row;
    	self.row += 1;
      Some((v, ret))
    }
}

fn main() {

	let mut v : Vec<f32> = vec![
		1.00, 0.00, 0.00,  0.00,  0.00, 0.00,
		1.00, 0.63, 0.39,  0.25,  0.16, 0.10,
		1.00, 1.26, 1.58,  1.98,  2.49, 3.13,
		1.00, 1.88, 3.55,  6.70, 12.62, 230.80,
		1.00, 2.51, 6.32, 15.88, 39.90, 100.28,
		1.00, 3.14, 9.87, 31.01, 97.41, 306.02];

	let mat = Matrix::new(&mut v, 6);

	let zero:f32 = 0.0;
	let mut r = Vec::new();
	let mut used: Vec<bool> = vec![false; mat.n];

	for i in 0..mat.n {

		let max;
		{
			let mat_iter = MatrixRowIter::new(&mat, &mut used, i);

			max = mat_iter
						.inspect(|&item| println!("{} {}", item.0, item.1) )
						.fold((0.0, -1),
							|max, item| if item.0.abs() > max.0 { item } else { max } )
						;
		}

		used[max.1] = true;
		println!("max {} {}", max.0, max.1);
		println!("=======");

		r.extend(mat.get_row_slice(max.1).iter());
	}

	let mut mat_out = Matrix::new(&mut r, mat.n);
	for i in 0..mat_out.n {
		for j in 0..mat_out.n {
			print!("{} ", mat_out.val(Idx(j, i)));
		}
		println!("  ");
	}

	let n= mat_out.n;
	for dia in 0..n {
		for row in dia+1..n {
			//let tmp = *mat_out.val(Idx(dia, row)) / *mat_out.val(Idx(dia, dia));
			for col in dia+1..n {
				//(*mat_out.val(Idx(col, row))) -= tmp;// * *mat_out.val(Idx(col, dia));
				//mat_out.val_mut(Idx(dia, row)) = 0.0;
				//let ref mut  rr : &mut &f32 = mat_out.val_mut(Idx(dia, row));
//				let rr : & mut f32   = &mut mat_out.val_mut(Idx(dia, row));
	//			println!("{}", rr);
				//*mat_out.val_mut(Idx(dia, row)) = 0.0;
				mat_out.set(Idx(dia, row), &zero);
				//*rr = 0.0;
			}
		}
	}

}
<|endoftext|>


<commit_before>use core::hint;

/// Tock programs' entry point. Called by the kernel at program start. Sets up
/// the stack then calls rust_start() for the remainder of setup.
#[doc(hidden)]
#[no_mangle]
#[naked]
#[link_section = ".start"]
pub unsafe extern "C" fn _start(
    app_start: usize,
    mem_start: usize,
    _memory_len: usize,
    app_heap_break: usize,
) -> ! {
    asm!("
        // Because ROPI-RWPI support in LLVM/rustc is incomplete, Rust
        // applications must be statically linked. An offset between the
        // location the program is linked at and its actual location in flash
        // would cause references in .data and .rodata to point to the wrong
        // data. To mitigate this, this section checks that .text (and .start)
        // are loaded at the correct location. If the application was linked and
        // loaded correctly, the location of the first instruction (read using
        // the Program Counter) will match the intended location of .start. We
        // don't have an easy way to signal an error, so for now we just yield
        // if the location is wrong.
        mov r4, pc
        sub r4, r4, #4    // r4 = pc
        ldr r5, =.start   // r5 = address of .start
        cmp r4, r5
        beq .Lstack_init  // Jump to stack initialization if pc was correct
        movw r0, #8       // LowLevelDebug driver number
        movw r1, #1       // LowLevelDebug 'print status code' command
        movw r2, #2       // LowLevelDebug relocation failed status code
        svc 2             // command() syscall
        .Lyield_loop:
        svc 0             // yield() syscall (in infinite loop)
        b .Lyield_loop

        .Lstack_init:
        // Compute the stacktop (stack_start). The stacktop is computed as
        // stack_size + mem_start plus padding to align the stack to a multiple
        // of 8 bytes. The 8 byte alignment is to follow ARM AAPCS:
        // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4127.html
        ldr r4, [r0, #36]  // r4 = app_start->stack_size
        add r4, r4, r1     // r4 = app_start->stack_size + mem_start
        add r4, #7         // r4 = app_start->stack_size + mem_start + 7
        bic r4, r4, #7     // r4 = (app_start->stack_size + mem_start + 7) & ~0x7
        mov sp, r4         // sp = r4

        // We need to pass app_start, stacktop and app_heap_break to rust_start.
        // Temporarily store them in r6, r7 and r8
        mov r6, r0
        mov r7, sp

        // Debug support, tell the kernel the stack location
        //
        // memop(10, stacktop)
        // r7 contains stacktop
        mov r0, #10
        mov r1, r7
        svc 4

        // Debug support, tell the kernel the heap_start location
        mov r0, r6
        ldr r4, [r0, #24] // r4 = app_start->bss_start
        ldr r5, [r0, #28] // r5 = app_start->bss_size
        add r4, r4, r5    // r4 = bss_start + bss_size
        //
        // memop(11, r4)
        mov r0, #11
        mov r1, r4
        svc 4

        // Store heap_start (and soon to be app_heap_break) in r8
        mov r8, r4

        // There is a possibility that stack + .data + .bss is greater than
        // 3072. Therefore setup the initial app_heap_break to heap_start (that
        // is zero initial heap) and let rust_start determine where the actual
        // app_heap_break should go.
        //
        // Also, because app_heap_break is where the unprivileged MPU region
        // ends, in case mem_start + stack + .data + .bss is greater than
        // initial app_heap_break (mem_start + 3072), we will get a memory fault
        // in rust_start when initializing .data and .bss. Setting
        // app_heap_break to heap_start avoids that.

        // memop(0, r8)
        mov r0, #0
        mov r1, r8
        svc 4

        // NOTE: If there is a hard-fault before this point, then
        //       process_detail_fmt in kernel/src/process.rs panics which
        //       will result in us losing the PC of the instruction
        //       generating the hard-fault. Therefore any code before
        //       this point is critical code

        // Setup parameters needed by rust_start
        // r6 (app_start), r7 (stacktop), r8 (app_heap_break)
        mov r0, r6
        mov r1, r7
        mov r2, r8

        // Call rust_start
        bl rust_start"
        :                                                              // No output operands
        : "{r0}"(app_start), "{r1}"(mem_start), "{r3}"(app_heap_break) // Input operands
        : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r12",
          "cc", "memory"                                               // Clobbers
        : "volatile"                                                   // Options
    );
    hint::unreachable_unchecked()
}
<commit_msg>Forcing T4 encoding<commit_after>use core::hint;

/// Tock programs' entry point. Called by the kernel at program start. Sets up
/// the stack then calls rust_start() for the remainder of setup.
#[doc(hidden)]
#[no_mangle]
#[naked]
#[link_section = ".start"]
pub unsafe extern "C" fn _start(
    app_start: usize,
    mem_start: usize,
    _memory_len: usize,
    app_heap_break: usize,
) -> ! {
    asm!("
        // Because ROPI-RWPI support in LLVM/rustc is incomplete, Rust
        // applications must be statically linked. An offset between the
        // location the program is linked at and its actual location in flash
        // would cause references in .data and .rodata to point to the wrong
        // data. To mitigate this, this section checks that .text (and .start)
        // are loaded at the correct location. If the application was linked and
        // loaded correctly, the location of the first instruction (read using
        // the Program Counter) will match the intended location of .start. We
        // don't have an easy way to signal an error, so for now we just yield
        // if the location is wrong.
        subw r4, pc, #4    // r4 = pc
        ldr r5, =.start   // r5 = address of .start
        cmp r4, r5
        beq .Lstack_init  // Jump to stack initialization if pc was correct
        movw r0, #8       // LowLevelDebug driver number
        movw r1, #1       // LowLevelDebug 'print status code' command
        movw r2, #2       // LowLevelDebug relocation failed status code
        svc 2             // command() syscall
        .Lyield_loop:
        svc 0             // yield() syscall (in infinite loop)
        b .Lyield_loop

        .Lstack_init:
        // Compute the stacktop (stack_start). The stacktop is computed as
        // stack_size + mem_start plus padding to align the stack to a multiple
        // of 8 bytes. The 8 byte alignment is to follow ARM AAPCS:
        // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4127.html
        ldr r4, [r0, #36]  // r4 = app_start->stack_size
        add r4, r4, r1     // r4 = app_start->stack_size + mem_start
        add r4, #7         // r4 = app_start->stack_size + mem_start + 7
        bic r4, r4, #7     // r4 = (app_start->stack_size + mem_start + 7) & ~0x7
        mov sp, r4         // sp = r4

        // We need to pass app_start, stacktop and app_heap_break to rust_start.
        // Temporarily store them in r6, r7 and r8
        mov r6, r0
        mov r7, sp

        // Debug support, tell the kernel the stack location
        //
        // memop(10, stacktop)
        // r7 contains stacktop
        mov r0, #10
        mov r1, r7
        svc 4

        // Debug support, tell the kernel the heap_start location
        mov r0, r6
        ldr r4, [r0, #24] // r4 = app_start->bss_start
        ldr r5, [r0, #28] // r5 = app_start->bss_size
        add r4, r4, r5    // r4 = bss_start + bss_size
        //
        // memop(11, r4)
        mov r0, #11
        mov r1, r4
        svc 4

        // Store heap_start (and soon to be app_heap_break) in r8
        mov r8, r4

        // There is a possibility that stack + .data + .bss is greater than
        // 3072. Therefore setup the initial app_heap_break to heap_start (that
        // is zero initial heap) and let rust_start determine where the actual
        // app_heap_break should go.
        //
        // Also, because app_heap_break is where the unprivileged MPU region
        // ends, in case mem_start + stack + .data + .bss is greater than
        // initial app_heap_break (mem_start + 3072), we will get a memory fault
        // in rust_start when initializing .data and .bss. Setting
        // app_heap_break to heap_start avoids that.

        // memop(0, r8)
        mov r0, #0
        mov r1, r8
        svc 4

        // NOTE: If there is a hard-fault before this point, then
        //       process_detail_fmt in kernel/src/process.rs panics which
        //       will result in us losing the PC of the instruction
        //       generating the hard-fault. Therefore any code before
        //       this point is critical code

        // Setup parameters needed by rust_start
        // r6 (app_start), r7 (stacktop), r8 (app_heap_break)
        mov r0, r6
        mov r1, r7
        mov r2, r8

        // Call rust_start
        bl rust_start"
        :                                                              // No output operands
        : "{r0}"(app_start), "{r1}"(mem_start), "{r3}"(app_heap_break) // Input operands
        : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r12",
          "cc", "memory"                                               // Clobbers
        : "volatile"                                                   // Options
    );
    hint::unreachable_unchecked()
}
<|endoftext|>


<commit_before>//! FIXME: write short doc here

use anyhow::{bail, Context, Result};
use std::{
    env,
    path::{Path, PathBuf},
    process::{Command, Output},
};

use ra_arena::{impl_arena_id, Arena, RawId};

#[derive(Default, Debug, Clone)]
pub struct Sysroot {
    crates: Arena<SysrootCrate, SysrootCrateData>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SysrootCrate(RawId);
impl_arena_id!(SysrootCrate);

#[derive(Debug, Clone)]
struct SysrootCrateData {
    name: String,
    root: PathBuf,
    deps: Vec<SysrootCrate>,
}

impl Sysroot {
    pub fn core(&self) -> Option<SysrootCrate> {
        self.by_name("core")
    }

    pub fn alloc(&self) -> Option<SysrootCrate> {
        self.by_name("alloc")
    }

    pub fn std(&self) -> Option<SysrootCrate> {
        self.by_name("std")
    }

    pub fn proc_macro(&self) -> Option<SysrootCrate> {
        self.by_name("proc_macro")
    }

    pub fn crates<'a>(&'a self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIterator + 'a {
        self.crates.iter().map(|(id, _data)| id)
    }

    pub fn discover(cargo_toml: &Path) -> Result<Sysroot> {
        let src = get_or_install_rust_src(cargo_toml)?;
        let mut sysroot = Sysroot { crates: Arena::default() };
        for name in SYSROOT_CRATES.trim().lines() {
            let root = src.join(format!("lib{}", name)).join("lib.rs");
            if root.exists() {
                sysroot.crates.alloc(SysrootCrateData {
                    name: name.into(),
                    root,
                    deps: Vec::new(),
                });
            }
        }
        if let Some(std) = sysroot.std() {
            for dep in STD_DEPS.trim().lines() {
                if let Some(dep) = sysroot.by_name(dep) {
                    sysroot.crates[std].deps.push(dep)
                }
            }
        }
        if let Some(alloc) = sysroot.by_name("alloc") {
            if let Some(core) = sysroot.core() {
                sysroot.crates[alloc].deps.push(core);
            }
        }
        Ok(sysroot)
    }

    fn by_name(&self, name: &str) -> Option<SysrootCrate> {
        self.crates.iter().find(|(_id, data)| data.name == name).map(|(id, _data)| id)
    }
}

fn create_command_text(program: &str, args: &[&str]) -> String {
    format!("{} {}", program, args.join(" "))
}

fn run_command_in_cargo_dir(cargo_toml: &Path, program: &str, args: &[&str]) -> Result<Output> {
    let output = Command::new(program)
        .current_dir(cargo_toml.parent().unwrap())
        .args(args)
        .output()
        .context(format!("{} failed", create_command_text(program, args)))?;
    if !output.status.success() {
        match output.status.code() {
            Some(code) => bail!(
                "failed to run the command: '{}' exited with code {}",
                create_command_text(program, args),
                code
            ),
            None => bail!(
                "failed to run the command: '{}' terminated by signal",
                create_command_text(program, args)
            ),
        };
    }
    Ok(output)
}

fn get_or_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> {
    if let Ok(path) = env::var("RUST_SRC_PATH") {
        return Ok(path.into());
    }
    let rustc_output = run_command_in_cargo_dir(cargo_toml, "rustc", &["--print", "sysroot"])?;
    let stdout = String::from_utf8(rustc_output.stdout)?;
    let sysroot_path = Path::new(stdout.trim());
    let src_path = sysroot_path.join("lib/rustlib/src/rust/src");

    if !src_path.exists() {
        run_command_in_cargo_dir(cargo_toml, "rustup", &["component", "add", "rust-src"])?;
    }
    if !src_path.exists() {
        bail!(
            "can't load standard library from sysroot\n\
            {}\n\
            (discovered via `rustc --print sysroot`)\n\
            try running `rustup component add rust-src` or set `RUST_SRC_PATH`",
            src_path.display(),
        )
    }
    Ok(src_path)
}

impl SysrootCrate {
    pub fn name(self, sysroot: &Sysroot) -> &str {
        &sysroot.crates[self].name
    }
    pub fn root(self, sysroot: &Sysroot) -> &Path {
        sysroot.crates[self].root.as_path()
    }
    pub fn root_dir(self, sysroot: &Sysroot) -> &Path {
        self.root(sysroot).parent().unwrap()
    }
    pub fn deps<'a>(self, sysroot: &'a Sysroot) -> impl Iterator<Item = SysrootCrate> + 'a {
        sysroot.crates[self].deps.iter().copied()
    }
}

const SYSROOT_CRATES: &str = "
std
core
alloc
collections
libc
panic_unwind
proc_macro
rustc_unicode
std_unicode
test
alloc_jemalloc
alloc_system
compiler_builtins
getopts
panic_unwind
panic_abort
rand
term
unwind
build_helper
rustc_asan
rustc_lsan
rustc_msan
rustc_tsan
syntax";

const STD_DEPS: &str = "
alloc
alloc_jemalloc
alloc_system
core
panic_abort
rand
compiler_builtins
unwind
rustc_asan
rustc_lsan
rustc_msan
rustc_tsan
build_helper";
<commit_msg>ra_project_model: migrate to Sysroot::alloc()<commit_after>//! FIXME: write short doc here

use anyhow::{bail, Context, Result};
use std::{
    env,
    path::{Path, PathBuf},
    process::{Command, Output},
};

use ra_arena::{impl_arena_id, Arena, RawId};

#[derive(Default, Debug, Clone)]
pub struct Sysroot {
    crates: Arena<SysrootCrate, SysrootCrateData>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SysrootCrate(RawId);
impl_arena_id!(SysrootCrate);

#[derive(Debug, Clone)]
struct SysrootCrateData {
    name: String,
    root: PathBuf,
    deps: Vec<SysrootCrate>,
}

impl Sysroot {
    pub fn core(&self) -> Option<SysrootCrate> {
        self.by_name("core")
    }

    pub fn alloc(&self) -> Option<SysrootCrate> {
        self.by_name("alloc")
    }

    pub fn std(&self) -> Option<SysrootCrate> {
        self.by_name("std")
    }

    pub fn proc_macro(&self) -> Option<SysrootCrate> {
        self.by_name("proc_macro")
    }

    pub fn crates<'a>(&'a self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIterator + 'a {
        self.crates.iter().map(|(id, _data)| id)
    }

    pub fn discover(cargo_toml: &Path) -> Result<Sysroot> {
        let src = get_or_install_rust_src(cargo_toml)?;
        let mut sysroot = Sysroot { crates: Arena::default() };
        for name in SYSROOT_CRATES.trim().lines() {
            let root = src.join(format!("lib{}", name)).join("lib.rs");
            if root.exists() {
                sysroot.crates.alloc(SysrootCrateData {
                    name: name.into(),
                    root,
                    deps: Vec::new(),
                });
            }
        }
        if let Some(std) = sysroot.std() {
            for dep in STD_DEPS.trim().lines() {
                if let Some(dep) = sysroot.by_name(dep) {
                    sysroot.crates[std].deps.push(dep)
                }
            }
        }
        if let Some(alloc) = sysroot.alloc() {
            if let Some(core) = sysroot.core() {
                sysroot.crates[alloc].deps.push(core);
            }
        }
        Ok(sysroot)
    }

    fn by_name(&self, name: &str) -> Option<SysrootCrate> {
        self.crates.iter().find(|(_id, data)| data.name == name).map(|(id, _data)| id)
    }
}

fn create_command_text(program: &str, args: &[&str]) -> String {
    format!("{} {}", program, args.join(" "))
}

fn run_command_in_cargo_dir(cargo_toml: &Path, program: &str, args: &[&str]) -> Result<Output> {
    let output = Command::new(program)
        .current_dir(cargo_toml.parent().unwrap())
        .args(args)
        .output()
        .context(format!("{} failed", create_command_text(program, args)))?;
    if !output.status.success() {
        match output.status.code() {
            Some(code) => bail!(
                "failed to run the command: '{}' exited with code {}",
                create_command_text(program, args),
                code
            ),
            None => bail!(
                "failed to run the command: '{}' terminated by signal",
                create_command_text(program, args)
            ),
        };
    }
    Ok(output)
}

fn get_or_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> {
    if let Ok(path) = env::var("RUST_SRC_PATH") {
        return Ok(path.into());
    }
    let rustc_output = run_command_in_cargo_dir(cargo_toml, "rustc", &["--print", "sysroot"])?;
    let stdout = String::from_utf8(rustc_output.stdout)?;
    let sysroot_path = Path::new(stdout.trim());
    let src_path = sysroot_path.join("lib/rustlib/src/rust/src");

    if !src_path.exists() {
        run_command_in_cargo_dir(cargo_toml, "rustup", &["component", "add", "rust-src"])?;
    }
    if !src_path.exists() {
        bail!(
            "can't load standard library from sysroot\n\
            {}\n\
            (discovered via `rustc --print sysroot`)\n\
            try running `rustup component add rust-src` or set `RUST_SRC_PATH`",
            src_path.display(),
        )
    }
    Ok(src_path)
}

impl SysrootCrate {
    pub fn name(self, sysroot: &Sysroot) -> &str {
        &sysroot.crates[self].name
    }
    pub fn root(self, sysroot: &Sysroot) -> &Path {
        sysroot.crates[self].root.as_path()
    }
    pub fn root_dir(self, sysroot: &Sysroot) -> &Path {
        self.root(sysroot).parent().unwrap()
    }
    pub fn deps<'a>(self, sysroot: &'a Sysroot) -> impl Iterator<Item = SysrootCrate> + 'a {
        sysroot.crates[self].deps.iter().copied()
    }
}

const SYSROOT_CRATES: &str = "
std
core
alloc
collections
libc
panic_unwind
proc_macro
rustc_unicode
std_unicode
test
alloc_jemalloc
alloc_system
compiler_builtins
getopts
panic_unwind
panic_abort
rand
term
unwind
build_helper
rustc_asan
rustc_lsan
rustc_msan
rustc_tsan
syntax";

const STD_DEPS: &str = "
alloc
alloc_jemalloc
alloc_system
core
panic_abort
rand
compiler_builtins
unwind
rustc_asan
rustc_lsan
rustc_msan
rustc_tsan
build_helper";
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::rc::Rc;

use syntex_syntax::ast::{self, Attribute, Name};
use syntex_syntax::ext::base::{
    self,
    Determinacy,
    MultiDecorator,
    MultiModifier,
    SyntaxExtension,
};
use syntex_syntax::ext::expand::Expansion;
use syntex_syntax::ext::hygiene::Mark;
use syntex_syntax::parse::ParseSess;
use syntex_syntax::ptr::P;

pub struct Resolver<'a> {
    session: &'a ParseSess,
    extensions: HashMap<ast::Name, Rc<SyntaxExtension>>,
}

impl<'a> Resolver<'a> {
    pub fn new(session: &'a ParseSess) -> Self {
        Resolver {
            session: session,
            extensions: HashMap::new(),
        }
    }
}

impl<'a> base::Resolver for Resolver<'a> {
    fn next_node_id(&mut self) -> ast::NodeId {
        ast::DUMMY_NODE_ID
    }
    fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }
    fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
    fn is_whitelisted_legacy_custom_derive(&self, _name: Name) -> bool { false }

    fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {}
    fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
        self.extensions.insert(ident.name, ext);
    }
    fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}

    fn resolve_imports(&mut self) {}
    fn find_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute> {
        for i in 0..attrs.len() {
            if let Some(ext) = self.extensions.get(&attrs[i].value.name) {
                match **ext {
                    MultiModifier(..) | MultiDecorator(..) => return Some(attrs.remove(i)),
                    _ => {}
                }
            }
        }
        None
    }
    fn find_extension(&mut self, _scope: Mark, name: ast::Name) -> Option<Rc<SyntaxExtension>> {
        self.extensions.get(&name).map(|ext| ext.clone())
    }
    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                     -> Result<Rc<SyntaxExtension>, Determinacy> {
        let ast::Path { ref segments, span } = *path;
        if segments.iter().any(|segment| segment.parameters.is_some()) {
            let kind =
                if segments.last().unwrap().parameters.is_some() { "macro" } else { "module" };
            let msg = format!("type parameters are not allowed on {}s", kind);
            self.session.span_diagnostic.span_err(path.span, &msg);
            return Err(Determinacy::Determined);
        }

        let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();

        if path.len() > 1 {
            // FIXME(syntex): Pass macros with module separators through to the generated source.
            self.session.span_diagnostic.span_err(path.span,
                                                    "expected macro name without module separators");
            return Err(Determinacy::Determined);
        }

        let name = path.segments[0].identifier.name;

        self.find_extension(scope, name).ok_or_else(|| {
            if force {
                let mut err =
                    self.session.span_diagnostic.struct_span_err(span, &format!("macro undefined: '{}!'", name));
                err.emit();
                Determinacy::Determined
            } else {
                Determinacy::Undetermined
            }
        })
    }
}
<commit_msg>Fix invalid references<commit_after>use std::collections::HashMap;
use std::rc::Rc;

use syntex_syntax::ast::{self, Attribute, Name};
use syntex_syntax::ext::base::{
    self,
    Determinacy,
    MultiDecorator,
    MultiModifier,
    SyntaxExtension,
};
use syntex_syntax::ext::expand::Expansion;
use syntex_syntax::ext::hygiene::Mark;
use syntex_syntax::parse::ParseSess;
use syntex_syntax::ptr::P;

pub struct Resolver<'a> {
    session: &'a ParseSess,
    extensions: HashMap<ast::Name, Rc<SyntaxExtension>>,
}

impl<'a> Resolver<'a> {
    pub fn new(session: &'a ParseSess) -> Self {
        Resolver {
            session: session,
            extensions: HashMap::new(),
        }
    }
}

impl<'a> base::Resolver for Resolver<'a> {
    fn next_node_id(&mut self) -> ast::NodeId {
        ast::DUMMY_NODE_ID
    }
    fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }
    fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
    fn is_whitelisted_legacy_custom_derive(&self, _name: Name) -> bool { false }

    fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {}
    fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
        self.extensions.insert(ident.name, ext);
    }
    fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}

    fn resolve_imports(&mut self) {}
    fn find_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute> {
        for i in 0..attrs.len() {
            if let Some(ext) = self.extensions.get(&attrs[i].value.name) {
                match **ext {
                    MultiModifier(..) | MultiDecorator(..) => return Some(attrs.remove(i)),
                    _ => {}
                }
            }
        }
        None
    }
    fn find_extension(&mut self, _scope: Mark, name: ast::Name) -> Option<Rc<SyntaxExtension>> {
        self.extensions.get(&name).map(|ext| ext.clone())
    }
    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                     -> Result<Rc<SyntaxExtension>, Determinacy> {
        let ast::Path { ref segments, span } = *path;
        if segments.iter().any(|segment| segment.parameters.is_some()) {
            let kind =
                if segments.last().unwrap().parameters.is_some() { "macro" } else { "module" };
            let msg = format!("type parameters are not allowed on {}s", kind);
            self.session.span_diagnostic.span_err(path.span, &msg);
            return Err(Determinacy::Determined);
        }

        let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();

        if path.len() > 1 {
            // FIXME(syntex): Pass macros with module separators through to the generated source.
            self.session.span_diagnostic.span_err(span, "expected macro name without module separators");
            return Err(Determinacy::Determined);
        }

        let name = path[0].name;

        self.find_extension(scope, name).ok_or_else(|| {
            if force {
                let mut err =
                    self.session.span_diagnostic.struct_span_err(span, &format!("macro undefined: '{}!'", name));
                err.emit();
                Determinacy::Determined
            } else {
                Determinacy::Undetermined
            }
        })
    }
}
<|endoftext|>


<commit_before>// Caveats - gdb prints any 8-bit value (meaning rust i8 and u8 values)
// as its numerical value along with its associated ASCII char, there
// doesn't seem to be any way around this. Also, gdb doesn't know
// about UTF-32 character encoding and will print a rust char as only
// its numerical value.

// min-lldb-version: 310

// This fails on lldb 6.0.1 on x86-64 Fedora 28; so ignore Linux for now.
// ignore-linux

// compile-flags:-g

// === GDB TESTS ===================================================================================

// gdb-command:run
// gdb-command:print b
// gdb-check:$1 = false
// gdb-command:print i
// gdb-check:$2 = -1
// gdb-command:print c
// gdbg-check:$3 = 97
// gdbr-check:$3 = 97 'a'
// gdb-command:print/d i8
// gdb-check:$4 = 68
// gdb-command:print i16
// gdb-check:$5 = -16
// gdb-command:print i32
// gdb-check:$6 = -32
// gdb-command:print i64
// gdb-check:$7 = -64
// gdb-command:print u
// gdb-check:$8 = 1
// gdb-command:print/d u8
// gdb-check:$9 = 100
// gdb-command:print u16
// gdb-check:$10 = 16
// gdb-command:print u32
// gdb-check:$11 = 32
// gdb-command:print u64
// gdb-check:$12 = 64
// gdb-command:print f32
// gdb-check:$13 = 2.5
// gdb-command:print f64
// gdb-check:$14 = 3.5
// gdb-command:print s
// gdbg-check:$15 = {data_ptr = [...] "Hello, World!", length = 13}
// gdbr-check:$15 = "Hello, World!"

// === LLDB TESTS ==================================================================================

// lldb-command:run
// lldb-command:print b
// lldbg-check:[...]$0 = false
// lldbr-check:(bool) b = false
// lldb-command:print i
// lldbg-check:[...]$1 = -1
// lldbr-check:(isize) i = -1

// NOTE: only rust-enabled lldb supports 32bit chars
// lldbr-command:print c
// lldbr-check:(char) c = 'a'

// lldb-command:print i8
// lldbg-check:[...]$2 = 'D'
// lldbr-check:(i8) i8 = 68
// lldb-command:print i16
// lldbg-check:[...]$3 = -16
// lldbr-check:(i16) i16 = -16
// lldb-command:print i32
// lldbg-check:[...]$4 = -32
// lldbr-check:(i32) i32 = -32
// lldb-command:print i64
// lldbg-check:[...]$5 = -64
// lldbr-check:(i64) i64 = -64
// lldb-command:print u
// lldbg-check:[...]$6 = 1
// lldbr-check:(usize) u = 1
// lldb-command:print u8
// lldbg-check:[...]$7 = 'd'
// lldbr-check:(u8) u8 = 100
// lldb-command:print u16
// lldbg-check:[...]$8 = 16
// lldbr-check:(u16) u16 = 16
// lldb-command:print u32
// lldbg-check:[...]$9 = 32
// lldbr-check:(u32) u32 = 32
// lldb-command:print u64
// lldbg-check:[...]$10 = 64
// lldbr-check:(u64) u64 = 64
// lldb-command:print f32
// lldbg-check:[...]$11 = 2.5
// lldbr-check:(f32) f32 = 2.5
// lldb-command:print f64
// lldbg-check:[...]$12 = 3.5
// lldbr-check:(f64) f64 = 3.5

// === CDB TESTS ===================================================================================

// cdb-command:g
// cdb-command:dx b
// cdb-check:b                : false [Type: bool]
// cdb-command:dx i
// cdb-check:i                : -1 [Type: __int64]
// The variable 'c' doesn't appear for some reason...
// cdb-command:dx i8
// cdb-check:i8               : 68 [Type: char]
// cdb-command:dx i16
// cdb-check:i16              : -16 [Type: short]
// cdb-command:dx i32
// cdb-check:i32              : -32 [Type: int]
// cdb-command:dx i64
// cdb-check:i64              : -64 [Type: __int64]
// cdb-command:dx u
// cdb-check:u                : 0x1 [Type: [...]]
// cdb-command:dx u8
// cdb-check:u8               : 0x64 [Type: unsigned char]
// cdb-command:dx u16
// cdb-check:u16              : 0x10 [Type: unsigned short]
// cdb-command:dx u32
// cdb-check:u32              : 0x20 [Type: unsigned int]
// cdb-command:dx u64
// cdb-check:u64              : 0x40 [Type: unsigned __int64]
// cdb-command:dx f32
// cdb-check:f32              : 2.500000 [Type: float]
// cdb-command:dx f64
// cdb-check:f64              : 3.500000 [Type: double]
// cdb-command:.enable_unicode 1
// cdb-command:dx  s
// cdb-check:s                : "Hello, World!" [Type: str]

#![allow(unused_variables)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]

fn main() {
    let b: bool = false;
    let i: isize = -1;
    let c: char = 'a';
    let i8: i8 = 68;
    let i16: i16 = -16;
    let i32: i32 = -32;
    let i64: i64 = -64;
    let u: usize = 1;
    let u8: u8 = 100;
    let u16: u16 = 16;
    let u32: u32 = 32;
    let u64: u64 = 64;
    let f32: f32 = 2.5;
    let f64: f64 = 3.5;
    let s: &str = "Hello, World!";
    _zzz(); // #break
}

fn _zzz() {()}
<commit_msg>Fix type name difference between i686 and x86_64 for test<commit_after>// Caveats - gdb prints any 8-bit value (meaning rust i8 and u8 values)
// as its numerical value along with its associated ASCII char, there
// doesn't seem to be any way around this. Also, gdb doesn't know
// about UTF-32 character encoding and will print a rust char as only
// its numerical value.

// min-lldb-version: 310

// This fails on lldb 6.0.1 on x86-64 Fedora 28; so ignore Linux for now.
// ignore-linux

// compile-flags:-g

// === GDB TESTS ===================================================================================

// gdb-command:run
// gdb-command:print b
// gdb-check:$1 = false
// gdb-command:print i
// gdb-check:$2 = -1
// gdb-command:print c
// gdbg-check:$3 = 97
// gdbr-check:$3 = 97 'a'
// gdb-command:print/d i8
// gdb-check:$4 = 68
// gdb-command:print i16
// gdb-check:$5 = -16
// gdb-command:print i32
// gdb-check:$6 = -32
// gdb-command:print i64
// gdb-check:$7 = -64
// gdb-command:print u
// gdb-check:$8 = 1
// gdb-command:print/d u8
// gdb-check:$9 = 100
// gdb-command:print u16
// gdb-check:$10 = 16
// gdb-command:print u32
// gdb-check:$11 = 32
// gdb-command:print u64
// gdb-check:$12 = 64
// gdb-command:print f32
// gdb-check:$13 = 2.5
// gdb-command:print f64
// gdb-check:$14 = 3.5
// gdb-command:print s
// gdbg-check:$15 = {data_ptr = [...] "Hello, World!", length = 13}
// gdbr-check:$15 = "Hello, World!"

// === LLDB TESTS ==================================================================================

// lldb-command:run
// lldb-command:print b
// lldbg-check:[...]$0 = false
// lldbr-check:(bool) b = false
// lldb-command:print i
// lldbg-check:[...]$1 = -1
// lldbr-check:(isize) i = -1

// NOTE: only rust-enabled lldb supports 32bit chars
// lldbr-command:print c
// lldbr-check:(char) c = 'a'

// lldb-command:print i8
// lldbg-check:[...]$2 = 'D'
// lldbr-check:(i8) i8 = 68
// lldb-command:print i16
// lldbg-check:[...]$3 = -16
// lldbr-check:(i16) i16 = -16
// lldb-command:print i32
// lldbg-check:[...]$4 = -32
// lldbr-check:(i32) i32 = -32
// lldb-command:print i64
// lldbg-check:[...]$5 = -64
// lldbr-check:(i64) i64 = -64
// lldb-command:print u
// lldbg-check:[...]$6 = 1
// lldbr-check:(usize) u = 1
// lldb-command:print u8
// lldbg-check:[...]$7 = 'd'
// lldbr-check:(u8) u8 = 100
// lldb-command:print u16
// lldbg-check:[...]$8 = 16
// lldbr-check:(u16) u16 = 16
// lldb-command:print u32
// lldbg-check:[...]$9 = 32
// lldbr-check:(u32) u32 = 32
// lldb-command:print u64
// lldbg-check:[...]$10 = 64
// lldbr-check:(u64) u64 = 64
// lldb-command:print f32
// lldbg-check:[...]$11 = 2.5
// lldbr-check:(f32) f32 = 2.5
// lldb-command:print f64
// lldbg-check:[...]$12 = 3.5
// lldbr-check:(f64) f64 = 3.5

// === CDB TESTS ===================================================================================

// cdb-command:g
// cdb-command:dx b
// cdb-check:b                : false [Type: bool]
// cdb-command:dx i
// cdb-check:i                : -1 [Type: [...]]
// The variable 'c' doesn't appear for some reason...
// cdb-command:dx i8
// cdb-check:i8               : 68 [Type: char]
// cdb-command:dx i16
// cdb-check:i16              : -16 [Type: short]
// cdb-command:dx i32
// cdb-check:i32              : -32 [Type: int]
// cdb-command:dx i64
// cdb-check:i64              : -64 [Type: __int64]
// cdb-command:dx u
// cdb-check:u                : 0x1 [Type: [...]]
// cdb-command:dx u8
// cdb-check:u8               : 0x64 [Type: unsigned char]
// cdb-command:dx u16
// cdb-check:u16              : 0x10 [Type: unsigned short]
// cdb-command:dx u32
// cdb-check:u32              : 0x20 [Type: unsigned int]
// cdb-command:dx u64
// cdb-check:u64              : 0x40 [Type: unsigned __int64]
// cdb-command:dx f32
// cdb-check:f32              : 2.500000 [Type: float]
// cdb-command:dx f64
// cdb-check:f64              : 3.500000 [Type: double]
// cdb-command:.enable_unicode 1
// cdb-command:dx  s
// cdb-check:s                : "Hello, World!" [Type: str]

#![allow(unused_variables)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]

fn main() {
    let b: bool = false;
    let i: isize = -1;
    let c: char = 'a';
    let i8: i8 = 68;
    let i16: i16 = -16;
    let i32: i32 = -32;
    let i64: i64 = -64;
    let u: usize = 1;
    let u8: u8 = 100;
    let u16: u16 = 16;
    let u32: u32 = 32;
    let u64: u64 = 64;
    let f32: f32 = 2.5;
    let f64: f64 = 3.5;
    let s: &str = "Hello, World!";
    _zzz(); // #break
}

fn _zzz() {()}
<|endoftext|>


<commit_before>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) 2015, Nathan Zadoks <nathan@nathan7.eu>
// See the LICENSE file included in this distribution.
use core::mem::{size_of, align_of};
use core::cmp::max;
use core::ptr;

use void::{self, Void};

use super::imp::STACK_ALIGN;

pub unsafe extern "C" fn rust_trampoline<F>(f: *const F) -> !
  where F: FnOnce() -> Void {
  void::unreachable(ptr::read(f)())
}

pub unsafe fn push<T>(spp: &mut *mut usize, value: T) -> *mut T {
  let mut sp = *spp as *mut T;
  sp = offset_mut(sp, -1);
  sp = align_down_mut(sp, max(align_of::<T>(), STACK_ALIGN));
  *sp = value;
  *spp = sp as *mut usize;
  sp
}

pub fn align_down_mut<T>(sp: *mut T, n: usize) -> *mut T {
  let sp = (sp as usize) & !(n - 1);
  sp as *mut T
}

// ptr::offset_mut is positive ints only
pub fn offset_mut<T>(ptr: *mut T, count: isize) -> *mut T {
  (ptr as isize + count * (size_of::<T>() as isize)) as *mut T
}
<commit_msg>don't drop uninitialised memory when pushing to stack<commit_after>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) 2015, Nathan Zadoks <nathan@nathan7.eu>
// See the LICENSE file included in this distribution.
use core::mem::{size_of, align_of};
use core::cmp::max;
use core::ptr;

use void::{self, Void};

use super::imp::STACK_ALIGN;

pub unsafe extern "C" fn rust_trampoline<F>(f: *const F) -> !
  where F: FnOnce() -> Void {
  void::unreachable(ptr::read(f)())
}

pub unsafe fn push<T>(spp: &mut *mut usize, value: T) -> *mut T {
  let mut sp = *spp as *mut T;
  sp = offset_mut(sp, -1);
  sp = align_down_mut(sp, max(align_of::<T>(), STACK_ALIGN));
  ptr::write(sp, value); // does not attempt to drop old value
  *spp = sp as *mut usize;
  sp
}

pub fn align_down_mut<T>(sp: *mut T, n: usize) -> *mut T {
  let sp = (sp as usize) & !(n - 1);
  sp as *mut T
}

// ptr::offset_mut is positive ints only
pub fn offset_mut<T>(ptr: *mut T, count: isize) -> *mut T {
  (ptr as isize + count * (size_of::<T>() as isize)) as *mut T
}
<|endoftext|>