<commit_before>extern crate cbindgen;

use cbindgen::*;
use std::path::Path;
use std::process::Command;
use std::{env, fs, str};

fn style_str(style: Style) -> &'static str {
    match style {
        Style::Both => "both",
        Style::Tag => "tag",
        Style::Type => "type",
    }
}

fn run_cbindgen(
    cbindgen_path: &'static str,
    path: &Path,
    output: &Path,
    language: Language,
    cpp_compat: bool,
    style: Option<Style>,
) {
    let program = Path::new(cbindgen_path);
    let mut command = Command::new(&program);
    match language {
        Language::Cxx => {}
        Language::C => {
            command.arg("--lang").arg("c");

            if cpp_compat {
                command.arg("--cpp-compat");
            }
        }
    }

    if let Some(style) = style {
        command.arg("--style").arg(style_str(style));
    }

    command.arg("-o").arg(output);

    if env::var("CBINDGEN_TEST_VERIFY").is_ok() {
        command.arg("--verify");
    }

    let mut config = path.clone().to_path_buf();
    config.set_extension("toml");
    if config.exists() {
        command.arg("--config").arg(config);
    }

    command.arg(path);

    println!("Running: {:?}", command);
    let cbindgen_output = command.output().expect("failed to execute process");
    assert!(
        cbindgen_output.status.success(),
        "cbindgen failed: {:?} with error: {}",
        output,
        str::from_utf8(&cbindgen_output.stderr).unwrap_or_default()
    );
}

fn compile(
    cbindgen_output: &Path,
    tests_path: &Path,
    tmp_dir: &Path,
    language: Language,
    style: Option<Style>,
    skip_warning_as_error: bool,
) {
    let cc = match language {
        Language::Cxx => env::var("CXX").unwrap_or_else(|_| "g++".to_owned()),
        Language::C => env::var("CC").unwrap_or_else(|_| "gcc".to_owned()),
    };

    let file_name = cbindgen_output
        .file_name()
        .expect("cbindgen output should be a file");
    let mut object = tmp_dir.join(file_name);
    object.set_extension("o");

    let mut command = Command::new(cc);
    command.arg("-D").arg("DEFINED");
    command.arg("-c").arg(cbindgen_output);
    command.arg("-o").arg(&object);
    command.arg("-I").arg(tests_path);
    command.arg("-Wall");
    if !skip_warning_as_error {
        command.arg("-Werror");
    }
    // `swift_name` is not recognzied by gcc.
    command.arg("-Wno-attributes");
    if let Language::Cxx = language {
        // enum class is a c++11 extension which makes g++ on macos 10.14 error out
        // inline variables are are a c++17 extension
        command.arg("-std=c++17");
        if let Ok(extra_flags) = env::var("CXXFLAGS") {
            command.args(extra_flags.split_whitespace());
        }
    } else {
        if let Ok(extra_flags) = env::var("CFLAGS") {
            command.args(extra_flags.split_whitespace());
        }
    }

    if let Some(style) = style {
        command.arg("-D");
        command.arg(format!(
            "CBINDGEN_STYLE_{}",
            style_str(style).to_uppercase()
        ));
    }

    println!("Running: {:?}", command);
    let out = command.output().expect("failed to compile");
    assert!(out.status.success(), "Output failed to compile: {:?}", out);

    if object.exists() {
        fs::remove_file(object).unwrap();
    }
}

fn run_compile_test(
    cbindgen_path: &'static str,
    name: &'static str,
    path: &Path,
    tmp_dir: &Path,
    language: Language,
    cpp_compat: bool,
    style: Option<Style>,
) {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let tests_path = Path::new(&crate_dir).join("tests");
    let mut generated_file = tests_path.join("expectations");
    if let Some(style) = style {
        match style {
            Style::Both => {
                generated_file.push("both");
            }
            Style::Tag => {
                generated_file.push("tag");
            }
            Style::Type => {}
        }
    }

    let ext = match language {
        Language::Cxx => "cpp",
        Language::C => {
            if cpp_compat {
                "compat.c"
            } else {
                "c"
            }
        }
    };
    let skip_warning_as_error_suffix = ".skip_warning_as_error";
    let skip_warning_as_error_position = name.rfind(skip_warning_as_error_suffix);
    let skip_warning_as_error = skip_warning_as_error_position.is_some();
    let mut source_file = format!("{}.{}", name, &ext);

    if skip_warning_as_error {
        source_file = format!(
            "{}.{}",
            &name[0..skip_warning_as_error_position.unwrap()],
            &ext
        );
    }
    generated_file.push(source_file);

    run_cbindgen(
        cbindgen_path,
        path,
        &generated_file,
        language,
        cpp_compat,
        style,
    );

    compile(
        &generated_file,
        &tests_path,
        tmp_dir,
        language,
        style,
        skip_warning_as_error,
    );

    if language == Language::C && cpp_compat {
        compile(
            &generated_file,
            &tests_path,
            tmp_dir,
            Language::Cxx,
            style,
            skip_warning_as_error,
        );
    }
}

fn test_file(cbindgen_path: &'static str, name: &'static str, filename: &'static str) {
    let test = Path::new(filename);
    let tmp_dir = tempfile::Builder::new()
        .prefix("cbindgen-test-output")
        .tempdir()
        .expect("Creating tmp dir failed");
    let tmp_dir = tmp_dir.path();
    for style in &[Style::Type, Style::Tag, Style::Both] {
        for cpp_compat in &[true, false] {
            run_compile_test(
                cbindgen_path,
                name,
                &test,
                tmp_dir,
                Language::C,
                *cpp_compat,
                Some(*style),
            );
        }
    }
    run_compile_test(
        cbindgen_path,
        name,
        &test,
        tmp_dir,
        Language::Cxx,
        /* cpp_compat = */ false,
        None,
    );
}

macro_rules! test_file {
    ($cbindgen_path:expr, $test_function_name:ident, $name:expr, $file:tt) => {
        #[test]
        fn $test_function_name() {
            test_file($cbindgen_path, $name, $file);
        }
    };
}

// This file is generated by build.rs
include!(concat!(env!("OUT_DIR"), "/tests.rs"));
<commit_msg>tests: Fix errors when testing with clang.<commit_after>extern crate cbindgen;

use cbindgen::*;
use std::path::Path;
use std::process::Command;
use std::{env, fs, str};

fn style_str(style: Style) -> &'static str {
    match style {
        Style::Both => "both",
        Style::Tag => "tag",
        Style::Type => "type",
    }
}

fn run_cbindgen(
    cbindgen_path: &'static str,
    path: &Path,
    output: &Path,
    language: Language,
    cpp_compat: bool,
    style: Option<Style>,
) {
    let program = Path::new(cbindgen_path);
    let mut command = Command::new(&program);
    match language {
        Language::Cxx => {}
        Language::C => {
            command.arg("--lang").arg("c");

            if cpp_compat {
                command.arg("--cpp-compat");
            }
        }
    }

    if let Some(style) = style {
        command.arg("--style").arg(style_str(style));
    }

    command.arg("-o").arg(output);

    if env::var("CBINDGEN_TEST_VERIFY").is_ok() {
        command.arg("--verify");
    }

    let mut config = path.clone().to_path_buf();
    config.set_extension("toml");
    if config.exists() {
        command.arg("--config").arg(config);
    }

    command.arg(path);

    println!("Running: {:?}", command);
    let cbindgen_output = command.output().expect("failed to execute process");
    assert!(
        cbindgen_output.status.success(),
        "cbindgen failed: {:?} with error: {}",
        output,
        str::from_utf8(&cbindgen_output.stderr).unwrap_or_default()
    );
}

fn compile(
    cbindgen_output: &Path,
    tests_path: &Path,
    tmp_dir: &Path,
    language: Language,
    style: Option<Style>,
    skip_warning_as_error: bool,
) {
    let cc = match language {
        Language::Cxx => env::var("CXX").unwrap_or_else(|_| "g++".to_owned()),
        Language::C => env::var("CC").unwrap_or_else(|_| "gcc".to_owned()),
    };

    let file_name = cbindgen_output
        .file_name()
        .expect("cbindgen output should be a file");
    let mut object = tmp_dir.join(file_name);
    object.set_extension("o");

    let mut command = Command::new(cc);
    command.arg("-D").arg("DEFINED");
    command.arg("-I").arg(tests_path);
    command.arg("-Wall");
    if !skip_warning_as_error {
        command.arg("-Werror");
    }
    // `swift_name` is not recognzied by gcc.
    command.arg("-Wno-attributes");
    // clang warns about unused const variables.
    command.arg("-Wno-unused-const-variable");
    // clang also warns about returning non-instantiated templates (they could
    // be specialized, but they're not so it's fine).
    command.arg("-Wno-return-type-c-linkage");
    if let Language::Cxx = language {
        // enum class is a c++11 extension which makes g++ on macos 10.14 error out
        // inline variables are are a c++17 extension
        command.arg("-std=c++17");
        // Prevents warnings when compiling .c files as c++.
        command.arg("-x").arg("c++");
        if let Ok(extra_flags) = env::var("CXXFLAGS") {
            command.args(extra_flags.split_whitespace());
        }
    } else {
        if let Ok(extra_flags) = env::var("CFLAGS") {
            command.args(extra_flags.split_whitespace());
        }
    }

    if let Some(style) = style {
        command.arg("-D");
        command.arg(format!(
            "CBINDGEN_STYLE_{}",
            style_str(style).to_uppercase()
        ));
    }

    command.arg("-o").arg(&object);
    command.arg("-c").arg(cbindgen_output);

    println!("Running: {:?}", command);
    let out = command.output().expect("failed to compile");
    assert!(out.status.success(), "Output failed to compile: {:?}", out);

    if object.exists() {
        fs::remove_file(object).unwrap();
    }
}

fn run_compile_test(
    cbindgen_path: &'static str,
    name: &'static str,
    path: &Path,
    tmp_dir: &Path,
    language: Language,
    cpp_compat: bool,
    style: Option<Style>,
) {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let tests_path = Path::new(&crate_dir).join("tests");
    let mut generated_file = tests_path.join("expectations");
    if let Some(style) = style {
        match style {
            Style::Both => {
                generated_file.push("both");
            }
            Style::Tag => {
                generated_file.push("tag");
            }
            Style::Type => {}
        }
    }

    let ext = match language {
        Language::Cxx => "cpp",
        Language::C => {
            if cpp_compat {
                "compat.c"
            } else {
                "c"
            }
        }
    };
    let skip_warning_as_error_suffix = ".skip_warning_as_error";
    let skip_warning_as_error_position = name.rfind(skip_warning_as_error_suffix);
    let skip_warning_as_error = skip_warning_as_error_position.is_some();
    let mut source_file = format!("{}.{}", name, &ext);

    if skip_warning_as_error {
        source_file = format!(
            "{}.{}",
            &name[0..skip_warning_as_error_position.unwrap()],
            &ext
        );
    }
    generated_file.push(source_file);

    run_cbindgen(
        cbindgen_path,
        path,
        &generated_file,
        language,
        cpp_compat,
        style,
    );

    compile(
        &generated_file,
        &tests_path,
        tmp_dir,
        language,
        style,
        skip_warning_as_error,
    );

    if language == Language::C && cpp_compat {
        compile(
            &generated_file,
            &tests_path,
            tmp_dir,
            Language::Cxx,
            style,
            skip_warning_as_error,
        );
    }
}

fn test_file(cbindgen_path: &'static str, name: &'static str, filename: &'static str) {
    let test = Path::new(filename);
    let tmp_dir = tempfile::Builder::new()
        .prefix("cbindgen-test-output")
        .tempdir()
        .expect("Creating tmp dir failed");
    let tmp_dir = tmp_dir.path();
    for style in &[Style::Type, Style::Tag, Style::Both] {
        for cpp_compat in &[true, false] {
            run_compile_test(
                cbindgen_path,
                name,
                &test,
                tmp_dir,
                Language::C,
                *cpp_compat,
                Some(*style),
            );
        }
    }
    run_compile_test(
        cbindgen_path,
        name,
        &test,
        tmp_dir,
        Language::Cxx,
        /* cpp_compat = */ false,
        None,
    );
}

macro_rules! test_file {
    ($cbindgen_path:expr, $test_function_name:ident, $name:expr, $file:tt) => {
        #[test]
        fn $test_function_name() {
            test_file($cbindgen_path, $name, $file);
        }
    };
}

// This file is generated by build.rs
include!(concat!(env!("OUT_DIR"), "/tests.rs"));
<|endoftext|>


<commit_before>fn main() {
    let v: Vec<i32> = Vec::new();

    // Macro usage for vector
    let v_from_macro = vec![1, 2, 3];

    let third: &i32 = &v_from_macro[2];
    let third_2: Option<&i32> = v_from_macro.get(2);

    let mut mutable_vector = Vec::new();

    mutable_vector.push(1);
    mutable_vector.push(2);
}
<commit_msg>Example of vector of enums<commit_after>fn main() {
    let v: Vec<i32> = Vec::new();

    // Macro usage for vector
    let v_from_macro = vec![1, 2, 3];

    let third: &i32 = &v_from_macro[2];
    let third_2: Option<&i32> = v_from_macro.get(2);

    let mut mutable_vector = Vec::new();

    mutable_vector.push(1);
    mutable_vector.push(2);

    let row = vec![
        SpreadsheetCell::Int(1),
        SpreadsheetCell::Float(1.23),
        SpreadsheetCell::Text(String::from("example"))
    ];
}

enum SpreadsheetCell {
    Int(i32),
    Float(f64),
    Text(String)
}<|endoftext|>


<commit_before>use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::PathBuf;
use structopt::StructOpt;

type Position = (isize, isize);

#[derive(Debug, Clone, Copy)]
enum Direction {
    Right(isize),
    Up(isize),
}

#[derive(Debug, Clone, Copy)]
struct Segment {
    origin: Position,
    direction: Direction,
}

#[derive(Debug)]
struct Wire {
    directions: Vec<Direction>,
}

impl Wire {
    fn segments(&self) -> Vec<Segment> {
        use Direction::*;
        let mut current_loc = (0, 0);
        let mut segments = Vec::new();
        for dir in self.directions.iter() {
            segments.push(Segment {
                origin: current_loc,
                direction: *dir,
            });
            current_loc = match dir {
                Right(dx) => (current_loc.0 + dx, current_loc.1),
                Up(dy) => (current_loc.0, current_loc.1 + dy),
            }
        }
        segments
    }
}

#[derive(Debug)]
struct ParseError;

impl std::str::FromStr for Wire {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use Direction::*;
        let mut directions = Vec::new();
        for segment in s.split(',') {
            let (dir, len) = segment.split_at(1);
            match (dir, len.parse::<isize>()) {
                ("R", Ok(len)) => directions.push(Right(len)),
                ("L", Ok(len)) => directions.push(Right(-len)),
                ("U", Ok(len)) => directions.push(Up(len)),
                ("D", Ok(len)) => directions.push(Up(-len)),
                _ => return Err(ParseError),
            }
        }
        Ok(Wire { directions })
    }
}

fn minmax(a: isize, b: isize) -> (isize, isize) {
    if a <= b {
        (a, b)
    } else {
        (b, a)
    }
}

fn intersection(a: Segment, b: Segment) -> Option<Position> {
    use Direction::*;
    match (a, b) {
        (
            Segment {
                origin: (ax, ay),
                direction: Right(dx),
            },
            Segment {
                origin: (bx, by),
                direction: Up(dy),
            },
        ) => {
            let ax_range = minmax(ax, ax + dx);
            let by_range = minmax(by, by + dy);
            if ax_range.0 < bx && bx < ax_range.1 && by_range.0 < ay && ay < by_range.1 {
                Some((bx, ay))
            } else {
                None
            }
        }
        (
            Segment {
                origin: (ax, ay),
                direction: Up(dy),
            },
            Segment {
                origin: (bx, by),
                direction: Right(dx),
            },
        ) => {
            let bx_range = minmax(bx, bx + dx);
            let ay_range = minmax(ay, ay + dy);
            if bx_range.0 < ax && ax < bx_range.1 && ay_range.0 < by && by < ay_range.1 {
                Some((ax, by))
            } else {
                None
            }
        }
        _ => None,
    }
}

fn manhattan_dist(a: &Position, b: &Position) -> isize {
    (a.0 - b.0).abs() + (a.1 - b.1).abs()
}

fn part1(first: &Wire, second: &Wire) -> isize {
    let first = first.segments();
    let second = second.segments();
    let closest = first
        .iter()
        .flat_map(|seg1| second.iter().map(|seg2| (seg1, seg2)).collect::<Vec<_>>())
        .filter_map(|(&a, &b)| intersection(a, b))
        .min_by_key(|pos| manhattan_dist(pos, &(0, 0)))
        .expect("No intersections found");
    manhattan_dist(&closest, &(0, 0))
}

fn main() {
    let handle = File::open(Opt::from_args().input).expect("error opening file");
    let input: Vec<_> = BufReader::new(handle)
        .lines()
        .map(|line| line.expect("Could not read input"))
        .map(|line| line.parse::<Wire>().expect("Could not parse wire"))
        .collect();
    assert_eq!(input.len(), 2);
    let first = input.get(0).unwrap();
    let second = input.get(1).unwrap();
    println!("Part 1: {}", part1(first, second));
}

#[derive(StructOpt)]
struct Opt {
    #[structopt(parse(from_os_str))]
    input: PathBuf,
}

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

    #[test]
    fn test_part1() {
        let expected = vec![
            (("R8,U5,L5,D3", "U7,R6,D4,L4"), 6),
            (
                (
                    "R75,D30,R83,U83,L12,D49,R71,U7,L72",
                    "U62,R66,U55,R34,D71,R55,D58,R83",
                ),
                159,
            ),
            (
                (
                    "R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51",
                    "U98,R91,D20,R16,D67,R40,U7,R15,U6,R7",
                ),
                135,
            ),
        ];
        for (input, output) in expected {
            assert_eq!(
                part1(&input.0.parse().unwrap(), &input.1.parse().unwrap()),
                output
            );
        }
    }
}
<commit_msg>2019 day 03 part 2<commit_after>use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::PathBuf;
use structopt::StructOpt;

type Position = (isize, isize);

#[derive(Debug, Clone, Copy)]
enum Direction {
    Right(isize),
    Up(isize),
}

#[derive(Debug, Clone, Copy)]
struct Segment {
    origin: Position,
    direction: Direction,
}

#[derive(Debug)]
struct Wire {
    directions: Vec<Direction>,
}

impl Wire {
    fn segments(&self) -> Vec<Segment> {
        use Direction::*;
        let mut current_loc = (0, 0);
        let mut segments = Vec::new();
        for dir in self.directions.iter() {
            segments.push(Segment {
                origin: current_loc,
                direction: *dir,
            });
            current_loc = match dir {
                Right(dx) => (current_loc.0 + dx, current_loc.1),
                Up(dy) => (current_loc.0, current_loc.1 + dy),
            }
        }
        segments
    }
}

#[derive(Debug)]
struct ParseError;

impl std::str::FromStr for Wire {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use Direction::*;
        let mut directions = Vec::new();
        for segment in s.split(',') {
            let (dir, len) = segment.split_at(1);
            match (dir, len.parse::<isize>()) {
                ("R", Ok(len)) => directions.push(Right(len)),
                ("L", Ok(len)) => directions.push(Right(-len)),
                ("U", Ok(len)) => directions.push(Up(len)),
                ("D", Ok(len)) => directions.push(Up(-len)),
                _ => return Err(ParseError),
            }
        }
        Ok(Wire { directions })
    }
}

fn minmax(a: isize, b: isize) -> (isize, isize) {
    if a <= b {
        (a, b)
    } else {
        (b, a)
    }
}

fn intersection(a: Segment, b: Segment) -> Option<Position> {
    use Direction::*;
    match (a, b) {
        (
            Segment {
                origin: (ax, ay),
                direction: Right(dx),
            },
            Segment {
                origin: (bx, by),
                direction: Up(dy),
            },
        ) => {
            let ax_range = minmax(ax, ax + dx);
            let by_range = minmax(by, by + dy);
            if ax_range.0 <= bx && bx <= ax_range.1 && by_range.0 <= ay && ay <= by_range.1 {
                Some((bx, ay))
            } else {
                None
            }
        }
        (
            Segment {
                origin: (ax, ay),
                direction: Up(dy),
            },
            Segment {
                origin: (bx, by),
                direction: Right(dx),
            },
        ) => {
            let bx_range = minmax(bx, bx + dx);
            let ay_range = minmax(ay, ay + dy);
            if bx_range.0 <= ax && ax <= bx_range.1 && ay_range.0 <= by && by <= ay_range.1 {
                Some((ax, by))
            } else {
                None
            }
        }
        _ => None,
    }
}

fn manhattan_dist(a: &Position, b: &Position) -> isize {
    (a.0 - b.0).abs() + (a.1 - b.1).abs()
}

fn part1(first: &Wire, second: &Wire) -> isize {
    let first = first.segments();
    let second = second.segments();
    let closest = first
        .iter()
        .flat_map(|seg1| second.iter().map(|seg2| (seg1, seg2)).collect::<Vec<_>>())
        .filter_map(|(&a, &b)| intersection(a, b))
        .filter(|pos| *pos != (0, 0))
        .min_by_key(|pos| manhattan_dist(pos, &(0, 0)))
        .expect("No intersections found");
    manhattan_dist(&closest, &(0, 0))
}

fn time_to_point(wire: &Wire, point: Position) -> Option<isize> {
    use Direction::*;
    let mut travelled = 0;
    for Segment { origin, direction } in wire.segments() {
        match direction {
            Right(dx) => {
                let x_range = minmax(origin.0, origin.0 + dx);
                if origin.1 == point.1 && x_range.0 <= point.0 && point.0 <= x_range.1 {
                    return Some(travelled + (origin.0 - point.0).abs());
                }
                travelled += dx.abs();
            }
            Up(dy) => {
                let y_range = minmax(origin.1, origin.1 + dy);
                if origin.0 == point.0 && y_range.0 <= point.1 && point.1 <= y_range.1 {
                    return Some(travelled + (origin.1 - point.1).abs());
                }
                travelled += dy.abs();
            }
        }
    }
    None
}

fn part2(first: &Wire, second: &Wire) -> isize {
    let first_segs = first.segments();
    let second_segs = second.segments();
    first_segs
        .iter()
        .flat_map(|seg1| {
            second_segs
                .iter()
                .map(|seg2| (seg1, seg2))
                .collect::<Vec<_>>()
        })
        .filter_map(|(&a, &b)| intersection(a, b))
        .filter(|pos| *pos != (0, 0))
        .map(|pos| {
            time_to_point(first, pos).expect("first never reaches pos")
                + time_to_point(second, pos).expect("second never reaches pos")
        })
        .min()
        .expect("No intersections found")
}

fn main() {
    let handle = File::open(Opt::from_args().input).expect("error opening file");
    let input: Vec<_> = BufReader::new(handle)
        .lines()
        .map(|line| line.expect("Could not read input"))
        .map(|line| line.parse::<Wire>().expect("Could not parse wire"))
        .collect();
    assert_eq!(input.len(), 2);
    let first = input.get(0).unwrap();
    let second = input.get(1).unwrap();
    println!("Part 1: {}", part1(first, second));
    println!("Part 2: {}", part2(first, second));
}

#[derive(StructOpt)]
struct Opt {
    #[structopt(parse(from_os_str))]
    input: PathBuf,
}

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

    #[test]
    fn test_part1() {
        let expected = vec![
            (("R8,U5,L5,D3", "U7,R6,D4,L4"), 6),
            (
                (
                    "R75,D30,R83,U83,L12,D49,R71,U7,L72",
                    "U62,R66,U55,R34,D71,R55,D58,R83",
                ),
                159,
            ),
            (
                (
                    "R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51",
                    "U98,R91,D20,R16,D67,R40,U7,R15,U6,R7",
                ),
                135,
            ),
        ];
        for (input, output) in expected {
            assert_eq!(
                part1(&input.0.parse().unwrap(), &input.1.parse().unwrap()),
                output
            );
        }
    }

    #[test]
    fn test_part2() {
        let expected = vec![
            (("R8,U5,L5,D3", "U7,R6,D4,L4"), 30),
            (
                (
                    "R75,D30,R83,U83,L12,D49,R71,U7,L72",
                    "U62,R66,U55,R34,D71,R55,D58,R83",
                ),
                610,
            ),
            (
                (
                    "R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51",
                    "U98,R91,D20,R16,D67,R40,U7,R15,U6,R7",
                ),
                410,
            ),
        ];
        for (input, output) in expected {
            assert_eq!(
                part2(&input.0.parse().unwrap(), &input.1.parse().unwrap()),
                output
            );
        }
    }
}
<|endoftext|>


<commit_before>use super::loader::Loader;
use super::util;
use crate::error::{Error, Result};
use std::io::{self, Write};
use std::path::Path;
use std::{fs, str};
use tree_sitter_tags::TagsContext;

pub fn generate_tags(loader: &Loader, scope: Option<&str>, paths: &[String]) -> Result<()> {
    let mut lang = None;
    if let Some(scope) = scope {
        lang = loader.language_configuration_for_scope(scope)?;
        if lang.is_none() {
            return Error::err(format!("Unknown scope '{}'", scope));
        }
    }

    let mut context = TagsContext::new();
    let cancellation_flag = util::cancel_on_stdin();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();

    for path in paths {
        let path = Path::new(&path);
        let (language, language_config) = match lang {
            Some(v) => v,
            None => match loader.language_configuration_for_file_name(path)? {
                Some(v) => v,
                None => {
                    eprintln!("No language found for path {:?}", path);
                    continue;
                }
            },
        };

        if let Some(tags_config) = language_config.tags_config(language)? {
            let path_str = format!("{:?}", path);
            writeln!(&mut stdout, "{}", &path_str[1..path_str.len() - 1])?;

            let source = fs::read(path)?;
            for tag in context.generate_tags(tags_config, &source, Some(&cancellation_flag))? {
                let tag = tag?;
                write!(
                    &mut stdout,
                    "  {:<8} {:<40}\t [{}] {:>9}-{:<9}",
                    tag.syntax_type,
                    str::from_utf8(&source[tag.name_range]).unwrap_or(""),
                    if tag.is_definition { "definition" } else { "reference" },
                    tag.span.start,
                    tag.span.end,
                )?;
                if let Some(docs) = tag.docs {
                    if docs.len() > 120 {
                        write!(&mut stdout, "\t{:?}...", &docs[0..120])?;
                    } else {
                        write!(&mut stdout, "\t{:?}", &docs)?;
                    }
                }
                writeln!(&mut stdout, "")?;
            }
        } else {
            eprintln!("No tags config found for path {:?}", path);
        }
    }

    Ok(())
}
<commit_msg>Shorten to def/ref<commit_after>use super::loader::Loader;
use super::util;
use crate::error::{Error, Result};
use std::io::{self, Write};
use std::path::Path;
use std::{fs, str};
use tree_sitter_tags::TagsContext;

pub fn generate_tags(loader: &Loader, scope: Option<&str>, paths: &[String]) -> Result<()> {
    let mut lang = None;
    if let Some(scope) = scope {
        lang = loader.language_configuration_for_scope(scope)?;
        if lang.is_none() {
            return Error::err(format!("Unknown scope '{}'", scope));
        }
    }

    let mut context = TagsContext::new();
    let cancellation_flag = util::cancel_on_stdin();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();

    for path in paths {
        let path = Path::new(&path);
        let (language, language_config) = match lang {
            Some(v) => v,
            None => match loader.language_configuration_for_file_name(path)? {
                Some(v) => v,
                None => {
                    eprintln!("No language found for path {:?}", path);
                    continue;
                }
            },
        };

        if let Some(tags_config) = language_config.tags_config(language)? {
            let path_str = format!("{:?}", path);
            writeln!(&mut stdout, "{}", &path_str[1..path_str.len() - 1])?;

            let source = fs::read(path)?;
            for tag in context.generate_tags(tags_config, &source, Some(&cancellation_flag))? {
                let tag = tag?;
                write!(
                    &mut stdout,
                    "  {:<8} {:<40}\t [{}] {:>9}-{:<9}",
                    tag.syntax_type,
                    str::from_utf8(&source[tag.name_range]).unwrap_or(""),
                    if tag.is_definition { "def" } else { "ref" },
                    tag.span.start,
                    tag.span.end,
                )?;
                if let Some(docs) = tag.docs {
                    if docs.len() > 120 {
                        write!(&mut stdout, "\t{:?}...", &docs[0..120])?;
                    } else {
                        write!(&mut stdout, "\t{:?}", &docs)?;
                    }
                }
                writeln!(&mut stdout, "")?;
            }
        } else {
            eprintln!("No tags config found for path {:?}", path);
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>use graph_algorithms as ga;
use nll_repr::repr;
use std::collections::BTreeMap;
use std::cell::RefCell;
use std::fmt;
use std::mem;
use std::iter;
use std::slice;

pub struct FuncGraph {
    func: repr::Func,
    start_block: BasicBlockIndex,
    blocks: Vec<BasicBlockKind>,
    successors: Vec<Vec<BasicBlockIndex>>,
    predecessors: Vec<Vec<BasicBlockIndex>>,
    block_indices: BTreeMap<repr::BasicBlock, BasicBlockIndex>,
    skolemized_end_indices: BTreeMap<repr::RegionName, BasicBlockIndex>,
    skolemized_end_actions: BTreeMap<repr::RegionName, [repr::Action; 1]>,
}

#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct BasicBlockIndex {
    index: usize,
}

#[derive(Copy, Clone, Debug)]
pub enum BasicBlockKind {
    Code(repr::BasicBlock),
    SkolemizedEnd(repr::RegionName),
}

#[derive(Copy, Clone, Debug)]
pub enum BasicBlockData<'a> {
    Code(&'a repr::BasicBlockData),
    SkolemizedEnd(&'a [repr::Action]),
}

impl FuncGraph {
    pub fn new(func: repr::Func) -> Self {
        let blocks: Vec<_> = func.data
            .keys()
            .map(|&bb| BasicBlockKind::Code(bb))
            .chain(
                func.regions
                    .iter()
                    .map(|rd| BasicBlockKind::SkolemizedEnd(rd.name)),
            )
            .collect();
        let block_indices: BTreeMap<_, _> = func.data
            .keys()
            .cloned()
            .enumerate()
            .map(|(index, block)| (block, BasicBlockIndex { index: index }))
            .collect();
        let skolemized_end_indices: BTreeMap<_, _> = func.regions
            .iter()
            .enumerate()
            .map(|(index, rd)| {
                (
                    rd.name,
                    BasicBlockIndex {
                        index: index + block_indices.len(),
                    },
                )
            })
            .collect();
        let skolemized_end_actions: BTreeMap<_, _> = func.regions
            .iter()
            .map(|rd| {
                (
                    rd.name,
                    [
                        repr::Action {
                            kind: repr::ActionKind::SkolemizedEnd(rd.name),
                            should_have_error: false,
                        },
                    ],
                )
            })
            .collect();
        let mut predecessors: Vec<_> = (0..blocks.len()).map(|_| Vec::new()).collect();
        let mut successors: Vec<_> = (0..blocks.len()).map(|_| Vec::new()).collect();

        let roots: Vec<_> = RegionRoots::extract(&func.regions)
            .iter()
            .map(|rn| skolemized_end_indices[rn])
            .collect();

        for (block, &index) in &block_indices {
            let data = &func.data[block];
            for successor in &data.successors {
                let successor_index = block_indices
                    .get(successor)
                    .cloned()
                    .unwrap_or_else(|| panic!("no index for {:?}", successor));
                successors[index.index].push(successor_index);
                predecessors[successor_index.index].push(index);
            }

            // Every block with no successors (and hence representing
            // a RETURN or a RESUME point) has, as a successor, the
            // root skolemized end points.
            if data.successors.is_empty() {
                for &root in &roots {
                    successors[index.index].push(root);
                    predecessors[root.index].push(index);
                }
            }
        }

        // Each `'a: 'b` relationship induces an edge `'b -> 'a`
        for a_decl in &func.regions {
            let a_index = skolemized_end_indices[&a_decl.name];

            for b_name in &a_decl.outlives {
                let b_index = skolemized_end_indices[b_name];

                successors[b_index.index].push(a_index);
                predecessors[a_index.index].push(b_index);
            }
        }

        let start_block = block_indices[&repr::BasicBlock::start()];

        FuncGraph {
            func,
            blocks,
            start_block,
            predecessors,
            successors,
            block_indices,
            skolemized_end_indices,
            skolemized_end_actions,
        }
    }

    pub fn block(&self, name: repr::BasicBlock) -> BasicBlockIndex {
        self.block_indices[&name]
    }

    pub fn skolemized_end(&self, name: repr::RegionName) -> BasicBlockIndex {
        self.skolemized_end_indices[&name]
    }

    pub fn block_data(&self, index: BasicBlockIndex) -> BasicBlockData {
        match self.blocks[index.index] {
            BasicBlockKind::Code(block) => BasicBlockData::Code(&self.func.data[&block]),
            BasicBlockKind::SkolemizedEnd(r) => BasicBlockData::SkolemizedEnd(
                &self.skolemized_end_actions[&r],
            ),
        }
    }

    pub fn decls(&self) -> &[repr::VariableDecl] {
        &self.func.decls
    }

    pub fn assertions(&self) -> &[repr::Assertion] {
        &self.func.assertions
    }

    pub fn struct_decls(&self) -> &[repr::StructDecl] {
        &self.func.structs
    }
}

impl ga::Graph for FuncGraph {
    type Node = BasicBlockIndex;

    fn num_nodes(&self) -> usize {
        self.func.data.len()
    }

    fn start_node(&self) -> BasicBlockIndex {
        self.start_block
    }

    fn predecessors<'graph>(
        &'graph self,
        node: BasicBlockIndex,
    ) -> <Self as ga::GraphPredecessors<'graph>>::Iter {
        self.predecessors[node.index].iter().cloned()
    }

    fn successors<'graph>(
        &'graph self,
        node: BasicBlockIndex,
    ) -> <Self as ga::GraphSuccessors<'graph>>::Iter {
        self.successors[node.index].iter().cloned()
    }
}

impl<'graph> ga::GraphPredecessors<'graph> for FuncGraph {
    type Item = BasicBlockIndex;
    type Iter = iter::Cloned<slice::Iter<'graph, BasicBlockIndex>>;
}

impl<'graph> ga::GraphSuccessors<'graph> for FuncGraph {
    type Item = BasicBlockIndex;
    type Iter = iter::Cloned<slice::Iter<'graph, BasicBlockIndex>>;
}

impl ga::NodeIndex for BasicBlockIndex {}

impl From<usize> for BasicBlockIndex {
    fn from(v: usize) -> BasicBlockIndex {
        BasicBlockIndex { index: v }
    }
}

impl Into<usize> for BasicBlockIndex {
    fn into(self) -> usize {
        self.index
    }
}

thread_local! {
    static NAMES: RefCell<Vec<BasicBlockKind>> = RefCell::new(vec![])
}

pub fn with_graph<OP, R>(g: &FuncGraph, op: OP) -> R
where
    OP: FnOnce() -> R,
{
    NAMES.with(|names| {
        let old_names = mem::replace(&mut *names.borrow_mut(), g.blocks.clone());
        let result = op();
        *names.borrow_mut() = old_names;
        result
    })
}

impl fmt::Debug for BasicBlockIndex {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        NAMES.with(|names| {
            let names = names.borrow();
            if !names.is_empty() {
                match names[self.index] {
                    BasicBlockKind::Code(bb) => write!(fmt, "{}", bb),
                    BasicBlockKind::SkolemizedEnd(rn) => write!(fmt, "{}", rn),
                }
            } else {
                write!(fmt, "BB{}", self.index)
            }
        })
    }
}

impl<'a> BasicBlockData<'a> {
    pub fn actions(self) -> &'a [repr::Action] {
        match self {
            BasicBlockData::Code(d) => &d.actions,
            BasicBlockData::SkolemizedEnd(actions) => actions,
        }
    }
}

struct RegionRoots<'a> {
    stack: Vec<repr::RegionName>,
    successors: &'a BTreeMap<repr::RegionName, Vec<repr::RegionName>>,
    state: BTreeMap<repr::RegionName, RegionState>,
}

struct RegionState {
    /// Does this region have a (non-cyclic) predecessor?
    has_pred: bool,
    visited: bool,
}

impl<'a> RegionRoots<'a> {
    fn extract(regions: &[repr::RegionDecl]) -> Vec<repr::RegionName> {
        // This is a bit tricky. Given something like `'a: 'b`, we want to produce
        //
        //   END -> 'b
        //   'b -> 'a
        //
        // But not END -> 'a, I don't think, because that would imply
        // that one can reach the end of 'a *without* passing through
        // the end of 'b!
        //
        // But be wary of `'a: 'b` and `'b: 'a`, in which case we need
        // an edge to one *or* the other, at least!
        //
        // So what are the ROOTS of the graph? We can create a GRAPH
        // with nodes equal to skolemized points and edges `'b -> 'a`
        // if `'a: 'b`. We then do a DFS.

        // Create a state for every region.
        let state: BTreeMap<_, _> = regions
            .iter()
            .map(|rd| {
                (
                    rd.name,
                    RegionState {
                        has_pred: false,
                        visited: false,
                    },
                )
            })
            .collect();

        // Create the edges. If `'a: 'b`, then `'b -> 'a`.
        let mut successors = BTreeMap::new();
        for rd in regions {
            for &rn_outlives in &rd.outlives {
                successors
                    .entry(rn_outlives)
                    .or_insert(vec![])
                    .push(rd.name);
            }
        }

        let stack = vec![];

        let mut roots = RegionRoots {
            state,
            successors: &successors,
            stack,
        };

        for rd in regions {
            roots.dfs(rd.name);
        }

        roots
            .state
            .iter()
            .filter(|&(_, state)| !state.has_pred)
            .map(|(&key, _)| key)
            .collect()
    }

    fn dfs(&mut self, region_name: repr::RegionName) {
        // Did we uncover a cycle? Then just stop.
        //
        // Hence if we have A -> B, B -> A and we visit A first and
        // then B:
        // - We will mark B as "has pred" but not A.
        // - Both will be marked as "visited", and hence when we next
        //   visit B, we'll ignore it.
        if self.stack.contains(&region_name) {
            return;
        }

        // Otherwise, if this node has a predecessor, mark it as a non-root.
        {
            let mut state = self.state.get_mut(&region_name).unwrap();

            if !self.stack.is_empty() {
                state.has_pred = true;
            }

            if state.visited {
                return;
            }

            state.visited = true;
        }

        // Visit successors now.
        self.stack.push(region_name);
        for &succ in &self.successors[&region_name] {
            self.dfs(succ);
        }
        self.stack.pop();
    }
}

#[test]
#[allow(bad_style)]
fn root_cycle() {
    let A = repr::RegionName::from("'a");
    let B = repr::RegionName::from("'b");
    let regions = vec![
        repr::RegionDecl {
            name: A,
            outlives: vec![B],
        },
        repr::RegionDecl {
            name: B,
            outlives: vec![A],
        },
    ];

    let roots = RegionRoots::extract(&regions);

    assert_eq!(roots, vec![A]);
}

#[test]
#[allow(bad_style)]
fn root_cycle_reachable_from_outside() {
    let A = repr::RegionName::from("'a");
    let B = repr::RegionName::from("'b");
    let C = repr::RegionName::from("'c");
    let regions = vec![
        repr::RegionDecl {
            name: A,
            outlives: vec![B, C],
        },
        repr::RegionDecl {
            name: B,
            outlives: vec![A],
        },
        repr::RegionDecl {
            name: C,
            outlives: vec![],
        },
    ];

    let roots = RegionRoots::extract(&regions);

    assert_eq!(roots, vec![C]);
}
<commit_msg>fix some silly bugs in skolemized-end graph points<commit_after>use graph_algorithms as ga;
use nll_repr::repr;
use std::collections::BTreeMap;
use std::cell::RefCell;
use std::fmt;
use std::mem;
use std::iter;
use std::slice;

pub struct FuncGraph {
    func: repr::Func,
    start_block: BasicBlockIndex,
    blocks: Vec<BasicBlockKind>,
    successors: Vec<Vec<BasicBlockIndex>>,
    predecessors: Vec<Vec<BasicBlockIndex>>,
    block_indices: BTreeMap<repr::BasicBlock, BasicBlockIndex>,
    skolemized_end_indices: BTreeMap<repr::RegionName, BasicBlockIndex>,
    skolemized_end_actions: BTreeMap<repr::RegionName, [repr::Action; 1]>,
}

#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct BasicBlockIndex {
    index: usize,
}

#[derive(Copy, Clone, Debug)]
pub enum BasicBlockKind {
    Code(repr::BasicBlock),
    SkolemizedEnd(repr::RegionName),
}

#[derive(Copy, Clone, Debug)]
pub enum BasicBlockData<'a> {
    Code(&'a repr::BasicBlockData),
    SkolemizedEnd(&'a [repr::Action]),
}

impl FuncGraph {
    pub fn new(func: repr::Func) -> Self {
        let blocks: Vec<_> = func.data
            .keys()
            .map(|&bb| BasicBlockKind::Code(bb))
            .chain(
                func.regions
                    .iter()
                    .map(|rd| BasicBlockKind::SkolemizedEnd(rd.name)),
            )
            .collect();
        let block_indices: BTreeMap<_, _> = func.data
            .keys()
            .cloned()
            .enumerate()
            .map(|(index, block)| (block, BasicBlockIndex { index: index }))
            .collect();
        let skolemized_end_indices: BTreeMap<_, _> = func.regions
            .iter()
            .enumerate()
            .map(|(index, rd)| {
                (
                    rd.name,
                    BasicBlockIndex {
                        index: index + block_indices.len(),
                    },
                )
            })
            .collect();
        let skolemized_end_actions: BTreeMap<_, _> = func.regions
            .iter()
            .map(|rd| {
                (
                    rd.name,
                    [
                        repr::Action {
                            kind: repr::ActionKind::SkolemizedEnd(rd.name),
                            should_have_error: false,
                        },
                    ],
                )
            })
            .collect();
        let mut predecessors: Vec<_> = (0..blocks.len()).map(|_| Vec::new()).collect();
        let mut successors: Vec<_> = (0..blocks.len()).map(|_| Vec::new()).collect();

        let roots: Vec<_> = RegionRoots::extract(&func.regions)
            .iter()
            .map(|rn| skolemized_end_indices[rn])
            .collect();

        for (block, &index) in &block_indices {
            let data = &func.data[block];
            for successor in &data.successors {
                let successor_index = block_indices
                    .get(successor)
                    .cloned()
                    .unwrap_or_else(|| panic!("no index for {:?}", successor));
                successors[index.index].push(successor_index);
                predecessors[successor_index.index].push(index);
            }

            // Every block with no successors (and hence representing
            // a RETURN or a RESUME point) has, as a successor, the
            // root skolemized end points.
            if data.successors.is_empty() {
                for &root in &roots {
                    successors[index.index].push(root);
                    predecessors[root.index].push(index);
                }
            }
        }

        // Each `'a: 'b` relationship induces an edge `'b -> 'a`
        for a_decl in &func.regions {
            let a_index = skolemized_end_indices[&a_decl.name];

            for b_name in &a_decl.outlives {
                let b_index = skolemized_end_indices[b_name];

                successors[b_index.index].push(a_index);
                predecessors[a_index.index].push(b_index);
            }
        }

        let start_block = block_indices[&repr::BasicBlock::start()];

        FuncGraph {
            func,
            blocks,
            start_block,
            predecessors,
            successors,
            block_indices,
            skolemized_end_indices,
            skolemized_end_actions,
        }
    }

    pub fn block(&self, name: repr::BasicBlock) -> BasicBlockIndex {
        self.block_indices[&name]
    }

    pub fn skolemized_end(&self, name: repr::RegionName) -> BasicBlockIndex {
        self.skolemized_end_indices[&name]
    }

    pub fn block_data(&self, index: BasicBlockIndex) -> BasicBlockData {
        match self.blocks[index.index] {
            BasicBlockKind::Code(block) => BasicBlockData::Code(&self.func.data[&block]),
            BasicBlockKind::SkolemizedEnd(r) => BasicBlockData::SkolemizedEnd(
                &self.skolemized_end_actions[&r],
            ),
        }
    }

    pub fn decls(&self) -> &[repr::VariableDecl] {
        &self.func.decls
    }

    pub fn assertions(&self) -> &[repr::Assertion] {
        &self.func.assertions
    }

    pub fn struct_decls(&self) -> &[repr::StructDecl] {
        &self.func.structs
    }
}

impl ga::Graph for FuncGraph {
    type Node = BasicBlockIndex;

    fn num_nodes(&self) -> usize {
        self.blocks.len()
    }

    fn start_node(&self) -> BasicBlockIndex {
        self.start_block
    }

    fn predecessors<'graph>(
        &'graph self,
        node: BasicBlockIndex,
    ) -> <Self as ga::GraphPredecessors<'graph>>::Iter {
        self.predecessors[node.index].iter().cloned()
    }

    fn successors<'graph>(
        &'graph self,
        node: BasicBlockIndex,
    ) -> <Self as ga::GraphSuccessors<'graph>>::Iter {
        self.successors[node.index].iter().cloned()
    }
}

impl<'graph> ga::GraphPredecessors<'graph> for FuncGraph {
    type Item = BasicBlockIndex;
    type Iter = iter::Cloned<slice::Iter<'graph, BasicBlockIndex>>;
}

impl<'graph> ga::GraphSuccessors<'graph> for FuncGraph {
    type Item = BasicBlockIndex;
    type Iter = iter::Cloned<slice::Iter<'graph, BasicBlockIndex>>;
}

impl ga::NodeIndex for BasicBlockIndex {}

impl From<usize> for BasicBlockIndex {
    fn from(v: usize) -> BasicBlockIndex {
        BasicBlockIndex { index: v }
    }
}

impl Into<usize> for BasicBlockIndex {
    fn into(self) -> usize {
        self.index
    }
}

thread_local! {
    static NAMES: RefCell<Vec<BasicBlockKind>> = RefCell::new(vec![])
}

pub fn with_graph<OP, R>(g: &FuncGraph, op: OP) -> R
where
    OP: FnOnce() -> R,
{
    NAMES.with(|names| {
        let old_names = mem::replace(&mut *names.borrow_mut(), g.blocks.clone());
        let result = op();
        *names.borrow_mut() = old_names;
        result
    })
}

impl fmt::Debug for BasicBlockIndex {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        NAMES.with(|names| {
            let names = names.borrow();
            if !names.is_empty() {
                match names[self.index] {
                    BasicBlockKind::Code(bb) => write!(fmt, "{}", bb),
                    BasicBlockKind::SkolemizedEnd(rn) => write!(fmt, "{}", rn),
                }
            } else {
                write!(fmt, "BB{}", self.index)
            }
        })
    }
}

impl<'a> BasicBlockData<'a> {
    pub fn actions(self) -> &'a [repr::Action] {
        match self {
            BasicBlockData::Code(d) => &d.actions,
            BasicBlockData::SkolemizedEnd(actions) => actions,
        }
    }
}

struct RegionRoots<'a> {
    stack: Vec<repr::RegionName>,
    successors: &'a BTreeMap<repr::RegionName, Vec<repr::RegionName>>,
    state: BTreeMap<repr::RegionName, RegionState>,
}

struct RegionState {
    /// Does this region have a (non-cyclic) predecessor?
    has_pred: bool,
    visited: bool,
}

impl<'a> RegionRoots<'a> {
    fn extract(regions: &[repr::RegionDecl]) -> Vec<repr::RegionName> {
        // This is a bit tricky. Given something like `'a: 'b`, we want to produce
        //
        //   END -> 'b
        //   'b -> 'a
        //
        // But not END -> 'a, I don't think, because that would imply
        // that one can reach the end of 'a *without* passing through
        // the end of 'b!
        //
        // But be wary of `'a: 'b` and `'b: 'a`, in which case we need
        // an edge to one *or* the other, at least!
        //
        // So what are the ROOTS of the graph? We can create a GRAPH
        // with nodes equal to skolemized points and edges `'b -> 'a`
        // if `'a: 'b`. We then do a DFS.

        // Create a state for every region.
        let state: BTreeMap<_, _> = regions
            .iter()
            .map(|rd| {
                (
                    rd.name,
                    RegionState {
                        has_pred: false,
                        visited: false,
                    },
                )
            })
            .collect();

        // Create the edges. If `'a: 'b`, then `'b -> 'a`.
        let mut successors = BTreeMap::new();
        for rd in regions {
            for &rn_outlives in &rd.outlives {
                successors
                    .entry(rn_outlives)
                    .or_insert(vec![])
                    .push(rd.name);
            }
        }

        let stack = vec![];

        let mut roots = RegionRoots {
            state,
            successors: &successors,
            stack,
        };

        for rd in regions {
            roots.dfs(rd.name);
        }

        roots
            .state
            .iter()
            .filter(|&(_, state)| !state.has_pred)
            .map(|(&key, _)| key)
            .collect()
    }

    fn dfs(&mut self, region_name: repr::RegionName) {
        // Did we uncover a cycle? Then just stop.
        //
        // Hence if we have A -> B, B -> A and we visit A first and
        // then B:
        // - We will mark B as "has pred" but not A.
        // - Both will be marked as "visited", and hence when we next
        //   visit B, we'll ignore it.
        if self.stack.contains(&region_name) {
            return;
        }

        // Otherwise, if this node has a predecessor, mark it as a non-root.
        {
            let mut state = self.state.get_mut(&region_name).unwrap();

            if !self.stack.is_empty() {
                state.has_pred = true;
            }

            if state.visited {
                return;
            }

            state.visited = true;
        }

        // Visit successors now.
        self.stack.push(region_name);
        for &succ in self.successors
            .get(&region_name)
            .into_iter()
            .flat_map(|v| v)
        {
            self.dfs(succ);
        }
        self.stack.pop();
    }
}

#[test]
#[allow(bad_style)]
fn root_cycle() {
    let A = repr::RegionName::from("'a");
    let B = repr::RegionName::from("'b");
    let regions = vec![
        repr::RegionDecl {
            name: A,
            outlives: vec![B],
        },
        repr::RegionDecl {
            name: B,
            outlives: vec![A],
        },
    ];

    let roots = RegionRoots::extract(&regions);

    assert_eq!(roots, vec![A]);
}

#[test]
#[allow(bad_style)]
fn root_cycle_reachable_from_outside() {
    let A = repr::RegionName::from("'a");
    let B = repr::RegionName::from("'b");
    let C = repr::RegionName::from("'c");
    let regions = vec![
        repr::RegionDecl {
            name: A,
            outlives: vec![B, C],
        },
        repr::RegionDecl {
            name: B,
            outlives: vec![A],
        },
        repr::RegionDecl {
            name: C,
            outlives: vec![],
        },
    ];

    let roots = RegionRoots::extract(&regions);

    assert_eq!(roots, vec![C]);
}
<|endoftext|>


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

use std::fs::File;
use std::io::prelude::*;
use std::io;
use std::path::Path;
use std::str;

#[derive(Clone)]
pub struct ExternalHtml{
    pub in_header: String,
    pub before_content: String,
    pub after_content: String
}

impl ExternalHtml {
    pub fn load(in_header: &[String], before_content: &[String], after_content: &[String])
            -> Option<ExternalHtml> {
        match (load_external_files(in_header),
               load_external_files(before_content),
               load_external_files(after_content)) {
            (Some(ih), Some(bc), Some(ac)) => Some(ExternalHtml {
                in_header: ih,
                before_content: bc,
                after_content: ac
            }),
            _ => None
        }
    }
}

pub fn load_string(input: &Path) -> io::Result<Option<String>> {
    let mut f = File::open(input)?;
    let mut d = Vec::new();
    f.read_to_end(&mut d)?;
    Ok(str::from_utf8(&d).map(|s| s.to_string()).ok())
}

macro_rules! load_or_return {
    ($input: expr, $cant_read: expr, $not_utf8: expr) => {
        {
            let input = Path::new(&$input[..]);
            match ::externalfiles::load_string(input) {
                Err(e) => {
                    let _ = writeln!(&mut io::stderr(),
                                     "error reading `{}`: {}", input.display(), e);
                    return $cant_read;
                }
                Ok(None) => {
                    let _ = writeln!(&mut io::stderr(),
                                     "error reading `{}`: not UTF-8", input.display());
                    return $not_utf8;
                }
                Ok(Some(s)) => s
            }
        }
    }
}

pub fn load_external_files(names: &[String]) -> Option<String> {
    let mut out = String::new();
    for name in names {
        out.push_str(&*load_or_return!(&name, None, None));
        out.push('\n');
    }
    Some(out)
}
<commit_msg>Add doc comments describing fields on `externalfiles::ExternalHtml`.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fs::File;
use std::io::prelude::*;
use std::io;
use std::path::Path;
use std::str;

#[derive(Clone)]
pub struct ExternalHtml{
    /// Content that will be included inline in the <head> section of a
    /// rendered Markdown file or generated documentation
    pub in_header: String,
    /// Content that will be included inline between <body> and the content of
    /// a rendered Markdown file or generated documentation
    pub before_content: String,
    /// Content that will be included inline between the content and </body> of
    /// a rendered Markdown file or generated documentation
    pub after_content: String
}

impl ExternalHtml {
    pub fn load(in_header: &[String], before_content: &[String], after_content: &[String])
            -> Option<ExternalHtml> {
        match (load_external_files(in_header),
               load_external_files(before_content),
               load_external_files(after_content)) {
            (Some(ih), Some(bc), Some(ac)) => Some(ExternalHtml {
                in_header: ih,
                before_content: bc,
                after_content: ac
            }),
            _ => None
        }
    }
}

pub fn load_string(input: &Path) -> io::Result<Option<String>> {
    let mut f = File::open(input)?;
    let mut d = Vec::new();
    f.read_to_end(&mut d)?;
    Ok(str::from_utf8(&d).map(|s| s.to_string()).ok())
}

macro_rules! load_or_return {
    ($input: expr, $cant_read: expr, $not_utf8: expr) => {
        {
            let input = Path::new(&$input[..]);
            match ::externalfiles::load_string(input) {
                Err(e) => {
                    let _ = writeln!(&mut io::stderr(),
                                     "error reading `{}`: {}", input.display(), e);
                    return $cant_read;
                }
                Ok(None) => {
                    let _ = writeln!(&mut io::stderr(),
                                     "error reading `{}`: not UTF-8", input.display());
                    return $not_utf8;
                }
                Ok(Some(s)) => s
            }
        }
    }
}

pub fn load_external_files(names: &[String]) -> Option<String> {
    let mut out = String::new();
    for name in names {
        out.push_str(&*load_or_return!(&name, None, None));
        out.push('\n');
    }
    Some(out)
}
<|endoftext|>


<commit_before>#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Request(pub RequestId, pub Vec<u8>);

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum AttrMacro {
    All,
    Fast,
    Full,
}

impl Copy for AttrMacro {}

#[derive(Debug, Eq, PartialEq)]
pub enum Response<'a> {
    Capabilities(Vec<Capability<'a>>),
    Continue {
        code: Option<ResponseCode<'a>>,
        information: Option<&'a str>,
    },
    Done {
        tag: RequestId,
        status: Status,
        code: Option<ResponseCode<'a>>,
        information: Option<&'a str>,
    },
    Data {
        status: Status,
        code: Option<ResponseCode<'a>>,
        information: Option<&'a str>,
    },
    Expunge(u32),
    Fetch(u32, Vec<AttributeValue<'a>>),
    MailboxData(MailboxDatum<'a>),
    IDs(Vec<u32>),
}

#[derive(Debug, Eq, PartialEq)]
pub enum Status {
    Ok,
    No,
    Bad,
    PreAuth,
    Bye,
}

#[derive(Debug, Eq, PartialEq)]
pub enum ResponseCode<'a> {
    Alert,
    BadCharset(Option<Vec<&'a str>>),
    Capabilities(Vec<Capability<'a>>),
    HighestModSeq(u64), // RFC 4551, section 3.1.1
    Parse,
    PermanentFlags(Vec<&'a str>),
    ReadOnly,
    ReadWrite,
    TryCreate,
    UidNext(u32),
    UidValidity(u32),
    Unseen(u32),
}

#[derive(Debug, Eq, PartialEq)]
pub enum StatusAttribute {
    HighestModSeq(u64), // RFC 4551
    Messages(u32),
    Recent(u32),
    UidNext(u32),
    UidValidity(u32),
    Unseen(u32),
}

#[derive(Debug, Eq, PartialEq)]
pub struct Metadata {
    pub entry: String,
    pub value: Option<String>,
}

#[derive(Debug, Eq, PartialEq)]
pub enum MailboxDatum<'a> {
    Exists(u32),
    Flags(Vec<&'a str>),
    List {
        flags: Vec<&'a str>,
        delimiter: Option<&'a str>,
        name: &'a str,
    },
    Status {
        mailbox: &'a str,
        status: Vec<StatusAttribute>,
    },
    Recent(u32),
    MetadataSolicited {
        mailbox: &'a str,
        values: Vec<Metadata>,
    },
    MetadataUnsolicited {
        mailbox: &'a str,
        values: Vec<&'a str>,
    },
}

#[derive(Debug, Eq, PartialEq, Hash)]
pub enum Capability<'a> {
    Imap4rev1,
    Auth(&'a str),
    Atom(&'a str),
}

#[derive(Debug, Eq, PartialEq)]
pub enum Attribute {
    Body,
    Envelope,
    Flags,
    InternalDate,
    ModSeq, // RFC 4551, section 3.3.2
    Rfc822,
    Rfc822Size,
    Rfc822Text,
    Uid,
}

#[derive(Debug, Eq, PartialEq)]
pub enum MessageSection {
    Header,
    Mime,
    Text,
}

#[derive(Debug, Eq, PartialEq)]
pub enum SectionPath {
    Full(MessageSection),
    Part(Vec<u32>, Option<MessageSection>),
}

#[allow(clippy::large_enum_variant)]
#[derive(Debug, Eq, PartialEq)]
pub enum AttributeValue<'a> {
    BodySection {
        section: Option<SectionPath>,
        index: Option<u32>,
        data: Option<&'a [u8]>,
    },
    BodyStructure(BodyStructure<'a>),
    Envelope(Box<Envelope<'a>>),
    Flags(Vec<&'a str>),
    InternalDate(&'a str),
    ModSeq(u64), // RFC 4551, section 3.3.2
    Rfc822(Option<&'a [u8]>),
    Rfc822Header(Option<&'a [u8]>),
    Rfc822Size(u32),
    Rfc822Text(Option<&'a [u8]>),
    Uid(u32),
}

#[allow(clippy::large_enum_variant)]
#[derive(Debug, Eq, PartialEq)]
pub enum BodyStructure<'a> {
    Basic {
        common: BodyContentCommon<'a>,
        other: BodyContentSinglePart<'a>,
        extension: Option<BodyExtension<'a>>,
    },
    Text {
        common: BodyContentCommon<'a>,
        other: BodyContentSinglePart<'a>,
        lines: u32,
        extension: Option<BodyExtension<'a>>,
    },
    Message {
        common: BodyContentCommon<'a>,
        other: BodyContentSinglePart<'a>,
        envelope: Envelope<'a>,
        body: Box<BodyStructure<'a>>,
        lines: u32,
        extension: Option<BodyExtension<'a>>,
    },
    Multipart {
        common: BodyContentCommon<'a>,
        bodies: Vec<BodyStructure<'a>>,
        extension: Option<BodyExtension<'a>>,
    },
}

#[derive(Debug, Eq, PartialEq)]
pub struct BodyContentCommon<'a> {
    pub ty: ContentType<'a>,
    pub disposition: Option<ContentDisposition<'a>>,
    pub language: Option<Vec<&'a str>>,
    pub location: Option<&'a str>,
}

#[derive(Debug, Eq, PartialEq)]
pub struct BodyContentSinglePart<'a> {
    pub id: Option<&'a str>,
    pub md5: Option<&'a str>,
    pub description: Option<&'a str>,
    pub transfer_encoding: ContentEncoding<'a>,
    pub octets: u32,
}

#[derive(Debug, Eq, PartialEq)]
pub struct ContentType<'a> {
    pub ty: &'a str,
    pub subtype: &'a str,
    pub params: BodyParams<'a>,
}

#[derive(Debug, Eq, PartialEq)]
pub struct ContentDisposition<'a> {
    pub ty: &'a str,
    pub params: BodyParams<'a>,
}

#[derive(Debug, Eq, PartialEq)]
pub enum ContentEncoding<'a> {
    SevenBit,
    EightBit,
    Binary,
    Base64,
    QuotedPrintable,
    Other(&'a str),
}

#[derive(Debug, Eq, PartialEq)]
pub enum BodyExtension<'a> {
    Num(u32),
    Str(Option<&'a str>),
    List(Vec<BodyExtension<'a>>),
}

pub type BodyParams<'a> = Option<Vec<(&'a str, &'a str)>>;

#[derive(Debug, Eq, PartialEq)]
pub struct Envelope<'a> {
    pub date: Option<&'a [u8]>,
    pub subject: Option<&'a [u8]>,
    pub from: Option<Vec<Address<'a>>>,
    pub sender: Option<Vec<Address<'a>>>,
    pub reply_to: Option<Vec<Address<'a>>>,
    pub to: Option<Vec<Address<'a>>>,
    pub cc: Option<Vec<Address<'a>>>,
    pub bcc: Option<Vec<Address<'a>>>,
    pub in_reply_to: Option<&'a [u8]>,
    pub message_id: Option<&'a [u8]>,
}

#[derive(Debug, Eq, PartialEq)]
pub struct Address<'a> {
    pub name: Option<&'a [u8]>,
    pub adl: Option<&'a [u8]>,
    pub mailbox: Option<&'a [u8]>,
    pub host: Option<&'a [u8]>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RequestId(pub String);

impl RequestId {
    pub fn as_bytes(&self) -> &[u8] {
        self.0.as_bytes()
    }
}

#[derive(Debug, Eq, PartialEq)]
pub enum State {
    NotAuthenticated,
    Authenticated,
    Selected,
    Logout,
}
<commit_msg>Implement Clone trait for Metadata.<commit_after>#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Request(pub RequestId, pub Vec<u8>);

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum AttrMacro {
    All,
    Fast,
    Full,
}

impl Copy for AttrMacro {}

#[derive(Debug, Eq, PartialEq)]
pub enum Response<'a> {
    Capabilities(Vec<Capability<'a>>),
    Continue {
        code: Option<ResponseCode<'a>>,
        information: Option<&'a str>,
    },
    Done {
        tag: RequestId,
        status: Status,
        code: Option<ResponseCode<'a>>,
        information: Option<&'a str>,
    },
    Data {
        status: Status,
        code: Option<ResponseCode<'a>>,
        information: Option<&'a str>,
    },
    Expunge(u32),
    Fetch(u32, Vec<AttributeValue<'a>>),
    MailboxData(MailboxDatum<'a>),
    IDs(Vec<u32>),
}

#[derive(Debug, Eq, PartialEq)]
pub enum Status {
    Ok,
    No,
    Bad,
    PreAuth,
    Bye,
}

#[derive(Debug, Eq, PartialEq)]
pub enum ResponseCode<'a> {
    Alert,
    BadCharset(Option<Vec<&'a str>>),
    Capabilities(Vec<Capability<'a>>),
    HighestModSeq(u64), // RFC 4551, section 3.1.1
    Parse,
    PermanentFlags(Vec<&'a str>),
    ReadOnly,
    ReadWrite,
    TryCreate,
    UidNext(u32),
    UidValidity(u32),
    Unseen(u32),
}

#[derive(Debug, Eq, PartialEq)]
pub enum StatusAttribute {
    HighestModSeq(u64), // RFC 4551
    Messages(u32),
    Recent(u32),
    UidNext(u32),
    UidValidity(u32),
    Unseen(u32),
}

#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Metadata {
    pub entry: String,
    pub value: Option<String>,
}

#[derive(Debug, Eq, PartialEq)]
pub enum MailboxDatum<'a> {
    Exists(u32),
    Flags(Vec<&'a str>),
    List {
        flags: Vec<&'a str>,
        delimiter: Option<&'a str>,
        name: &'a str,
    },
    Status {
        mailbox: &'a str,
        status: Vec<StatusAttribute>,
    },
    Recent(u32),
    MetadataSolicited {
        mailbox: &'a str,
        values: Vec<Metadata>,
    },
    MetadataUnsolicited {
        mailbox: &'a str,
        values: Vec<&'a str>,
    },
}

#[derive(Debug, Eq, PartialEq, Hash)]
pub enum Capability<'a> {
    Imap4rev1,
    Auth(&'a str),
    Atom(&'a str),
}

#[derive(Debug, Eq, PartialEq)]
pub enum Attribute {
    Body,
    Envelope,
    Flags,
    InternalDate,
    ModSeq, // RFC 4551, section 3.3.2
    Rfc822,
    Rfc822Size,
    Rfc822Text,
    Uid,
}

#[derive(Debug, Eq, PartialEq)]
pub enum MessageSection {
    Header,
    Mime,
    Text,
}

#[derive(Debug, Eq, PartialEq)]
pub enum SectionPath {
    Full(MessageSection),
    Part(Vec<u32>, Option<MessageSection>),
}

#[allow(clippy::large_enum_variant)]
#[derive(Debug, Eq, PartialEq)]
pub enum AttributeValue<'a> {
    BodySection {
        section: Option<SectionPath>,
        index: Option<u32>,
        data: Option<&'a [u8]>,
    },
    BodyStructure(BodyStructure<'a>),
    Envelope(Box<Envelope<'a>>),
    Flags(Vec<&'a str>),
    InternalDate(&'a str),
    ModSeq(u64), // RFC 4551, section 3.3.2
    Rfc822(Option<&'a [u8]>),
    Rfc822Header(Option<&'a [u8]>),
    Rfc822Size(u32),
    Rfc822Text(Option<&'a [u8]>),
    Uid(u32),
}

#[allow(clippy::large_enum_variant)]
#[derive(Debug, Eq, PartialEq)]
pub enum BodyStructure<'a> {
    Basic {
        common: BodyContentCommon<'a>,
        other: BodyContentSinglePart<'a>,
        extension: Option<BodyExtension<'a>>,
    },
    Text {
        common: BodyContentCommon<'a>,
        other: BodyContentSinglePart<'a>,
        lines: u32,
        extension: Option<BodyExtension<'a>>,
    },
    Message {
        common: BodyContentCommon<'a>,
        other: BodyContentSinglePart<'a>,
        envelope: Envelope<'a>,
        body: Box<BodyStructure<'a>>,
        lines: u32,
        extension: Option<BodyExtension<'a>>,
    },
    Multipart {
        common: BodyContentCommon<'a>,
        bodies: Vec<BodyStructure<'a>>,
        extension: Option<BodyExtension<'a>>,
    },
}

#[derive(Debug, Eq, PartialEq)]
pub struct BodyContentCommon<'a> {
    pub ty: ContentType<'a>,
    pub disposition: Option<ContentDisposition<'a>>,
    pub language: Option<Vec<&'a str>>,
    pub location: Option<&'a str>,
}

#[derive(Debug, Eq, PartialEq)]
pub struct BodyContentSinglePart<'a> {
    pub id: Option<&'a str>,
    pub md5: Option<&'a str>,
    pub description: Option<&'a str>,
    pub transfer_encoding: ContentEncoding<'a>,
    pub octets: u32,
}

#[derive(Debug, Eq, PartialEq)]
pub struct ContentType<'a> {
    pub ty: &'a str,
    pub subtype: &'a str,
    pub params: BodyParams<'a>,
}

#[derive(Debug, Eq, PartialEq)]
pub struct ContentDisposition<'a> {
    pub ty: &'a str,
    pub params: BodyParams<'a>,
}

#[derive(Debug, Eq, PartialEq)]
pub enum ContentEncoding<'a> {
    SevenBit,
    EightBit,
    Binary,
    Base64,
    QuotedPrintable,
    Other(&'a str),
}

#[derive(Debug, Eq, PartialEq)]
pub enum BodyExtension<'a> {
    Num(u32),
    Str(Option<&'a str>),
    List(Vec<BodyExtension<'a>>),
}

pub type BodyParams<'a> = Option<Vec<(&'a str, &'a str)>>;

#[derive(Debug, Eq, PartialEq)]
pub struct Envelope<'a> {
    pub date: Option<&'a [u8]>,
    pub subject: Option<&'a [u8]>,
    pub from: Option<Vec<Address<'a>>>,
    pub sender: Option<Vec<Address<'a>>>,
    pub reply_to: Option<Vec<Address<'a>>>,
    pub to: Option<Vec<Address<'a>>>,
    pub cc: Option<Vec<Address<'a>>>,
    pub bcc: Option<Vec<Address<'a>>>,
    pub in_reply_to: Option<&'a [u8]>,
    pub message_id: Option<&'a [u8]>,
}

#[derive(Debug, Eq, PartialEq)]
pub struct Address<'a> {
    pub name: Option<&'a [u8]>,
    pub adl: Option<&'a [u8]>,
    pub mailbox: Option<&'a [u8]>,
    pub host: Option<&'a [u8]>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RequestId(pub String);

impl RequestId {
    pub fn as_bytes(&self) -> &[u8] {
        self.0.as_bytes()
    }
}

#[derive(Debug, Eq, PartialEq)]
pub enum State {
    NotAuthenticated,
    Authenticated,
    Selected,
    Logout,
}
<|endoftext|>


<commit_before>use petgraph::graph::NodeIndex;

use rustwlc::WlcView;

use super::super::LayoutTree;
use super::super::core::Direction;
use super::super::core::container::{Container, ContainerType, Handle, Layout};

impl LayoutTree {
    pub fn move_focus_recurse(&mut self, node_ix: NodeIndex, direction: Direction) -> Result<NodeIndex, ()> {
        match self.tree[node_ix].get_type() {
            ContainerType::View | ContainerType::Container => { /* continue */ },
            _ => return Err(())
        }
        let parent_ix = self.tree.parent_of(node_ix)
            .expect("Active ix had no parent");
        match self.tree[parent_ix] {
            Container::Container { layout, .. } => {
                match (layout, direction) {
                    (Layout::Horizontal, Direction::Left) |
                    (Layout::Horizontal, Direction::Right) |
                    (Layout::Vertical, Direction::Up) |
                    (Layout::Vertical, Direction::Down) => {
                        let siblings = self.tree.children_of(parent_ix);
                        let cur_index = siblings.iter().position(|node| {
                            *node == node_ix
                        }).expect("Could not find self in parent");
                        let maybe_new_index = match direction {
                            Direction::Right | Direction::Down => {
                                cur_index.checked_add(1)
                            }
                            Direction::Left  | Direction::Up => {
                                cur_index.checked_sub(1)
                            }
                        };
                        if maybe_new_index.is_some() &&
                            maybe_new_index.unwrap() < siblings.len() {
                                // There is a sibling to move to.
                                let new_index = maybe_new_index.unwrap();
                                let new_active_ix = siblings[new_index];
                                match self.tree[new_active_ix].get_type() {
                                    ContainerType::Container => {
                                        let path_ix = self.tree.follow_path(new_active_ix);
                                        // If the path wasn't complete, find the first view and focus on that
                                        let node_ix = (self.tree.descendant_of_type(path_ix, ContainerType::View)).unwrap();
                                        let parent_ix = (self.tree.parent_of(node_ix)).unwrap();
                                        match self.tree[node_ix].get_type() {
                                            ContainerType::View | ContainerType::Container => {},
                                            _ => panic!("Following path did not lead to a container or a view!")
                                        }
                                        trace!("Moving to different view {:?} in container {:?}",
                                                self.tree[node_ix], self.tree[parent_ix]);
                                        return Ok(node_ix);
                                    },
                                    ContainerType::View => {
                                        trace!("Moving to other view {:?}", self.tree[new_active_ix]);
                                        return Ok(new_active_ix)
                                    },
                                    _ => unreachable!()
                                };
                            }
                    },
                    _ => { /* We are moving out of siblings, recurse */ }
                }
            }
            Container::Workspace { .. } => {
                return Err(());
            }
            _ => unreachable!()
        }
        let parent_ix = self.tree.parent_of(node_ix)
            .expect("Node had no parent");
        return self.move_focus_recurse(parent_ix, direction);
    }

    /// Updates the current active container to be the next container or view
    /// to focus on after the previous view/container was moved/removed.
    ///
    /// A new view will tried to be set, starting with the children of the
    /// parent node. If a view cannot be found there, it starts climbing the
    /// tree until either a view is found or the workspace is (in which case
    /// it set the active container to the root container of the workspace)
    pub fn focus_on_next_container(&mut self, mut parent_ix: NodeIndex) {
        while self.tree.node_type(parent_ix)
            .expect("Node not part of the tree") != ContainerType::Workspace {
            if let Some(view_ix) = self.tree.descendant_of_type_right(parent_ix,
                                                            ContainerType::View) {
                match self.tree[view_ix]
                                    .get_handle().expect("view had no handle") {
                    Handle::View(view) => view.focus(),
                    _ => panic!("View had an output handle")
                }
                trace!("Active container set to view at {:?}", view_ix);
                let id = self.tree[view_ix].get_id();
                self.set_active_container(id)
                    .expect("Could not set active container");
                return;
            }
            parent_ix = self.tree.ancestor_of_type(parent_ix,
                                                    ContainerType::Container)
                .unwrap_or_else(|| {
                    self.tree.ancestor_of_type(parent_ix, ContainerType::Workspace)
                        .expect("Container was not part of a workspace")
                });
        }
        // If this is reached, parent is workspace
        let container_ix = self.tree.children_of(parent_ix)[0];
        let root_c_children = self.tree.children_of(container_ix);
        if root_c_children.len() > 0 {
            let new_active_ix = self.tree.descendant_of_type(root_c_children[0],
                                                                ContainerType::View)
                .unwrap_or(root_c_children[0]);
            let id = self.tree[new_active_ix].get_id();
            self.set_active_container(id)
                .expect("Could not set active container");
            match self.tree[new_active_ix] {
                Container::View { ref handle, .. } => handle.focus(),
                _ => {}
            };
            return;
        }
        trace!("Active container set to container {:?}", container_ix);
        let id = self.tree[container_ix].get_id();
        self.set_active_container(id)
            .expect("Could not set active container");

        // Update focus to new container
        self.get_active_container().map(|con| match *con {
            Container::View { ref handle, .. } => handle.focus(),
            Container::Container { .. } => WlcView::root().focus(),
            _ => panic!("Active container not view or container!")
        });
    }
}
<commit_msg>Focus will not panic if can't find view<commit_after>use petgraph::graph::NodeIndex;

use rustwlc::WlcView;

use super::super::LayoutTree;
use super::super::core::Direction;
use super::super::core::container::{Container, ContainerType, Handle, Layout};

impl LayoutTree {
    pub fn move_focus_recurse(&mut self, node_ix: NodeIndex, direction: Direction) -> Result<NodeIndex, ()> {
        match self.tree[node_ix].get_type() {
            ContainerType::View | ContainerType::Container => { /* continue */ },
            _ => return Err(())
        }
        let parent_ix = self.tree.parent_of(node_ix)
            .expect("Active ix had no parent");
        match self.tree[parent_ix] {
            Container::Container { layout, .. } => {
                match (layout, direction) {
                    (Layout::Horizontal, Direction::Left) |
                    (Layout::Horizontal, Direction::Right) |
                    (Layout::Vertical, Direction::Up) |
                    (Layout::Vertical, Direction::Down) => {
                        let siblings = self.tree.children_of(parent_ix);
                        let cur_index = siblings.iter().position(|node| {
                            *node == node_ix
                        }).expect("Could not find self in parent");
                        let maybe_new_index = match direction {
                            Direction::Right | Direction::Down => {
                                cur_index.checked_add(1)
                            }
                            Direction::Left  | Direction::Up => {
                                cur_index.checked_sub(1)
                            }
                        };
                        if maybe_new_index.is_some() &&
                            maybe_new_index.unwrap() < siblings.len() {
                                // There is a sibling to move to.
                                let new_index = maybe_new_index.unwrap();
                                let new_active_ix = siblings[new_index];
                                match self.tree[new_active_ix].get_type() {
                                    ContainerType::Container => {
                                        let path_ix = self.tree.follow_path(new_active_ix);
                                        // If the path wasn't complete, find the first view and focus on that
                                        let node_ix = match self.tree.descendant_of_type(path_ix, ContainerType::View) {
                                            Some(ix) => ix,
                                            None => {
                                                warn!("Could not find view while changing focus in a container");
                                                return Err(())
                                            }
                                        };
                                        let parent_ix = (self.tree.parent_of(node_ix)).unwrap();
                                        match self.tree[node_ix].get_type() {
                                            ContainerType::View | ContainerType::Container => {},
                                            _ => panic!("Following path did not lead to a container or a view!")
                                        }
                                        trace!("Moving to different view {:?} in container {:?}",
                                                self.tree[node_ix], self.tree[parent_ix]);
                                        return Ok(node_ix);
                                    },
                                    ContainerType::View => {
                                        trace!("Moving to other view {:?}", self.tree[new_active_ix]);
                                        return Ok(new_active_ix)
                                    },
                                    _ => unreachable!()
                                };
                            }
                    },
                    _ => { /* We are moving out of siblings, recurse */ }
                }
            }
            Container::Workspace { .. } => {
                return Err(());
            }
            _ => unreachable!()
        }
        let parent_ix = self.tree.parent_of(node_ix)
            .expect("Node had no parent");
        return self.move_focus_recurse(parent_ix, direction);
    }

    /// Updates the current active container to be the next container or view
    /// to focus on after the previous view/container was moved/removed.
    ///
    /// A new view will tried to be set, starting with the children of the
    /// parent node. If a view cannot be found there, it starts climbing the
    /// tree until either a view is found or the workspace is (in which case
    /// it set the active container to the root container of the workspace)
    pub fn focus_on_next_container(&mut self, mut parent_ix: NodeIndex) {
        while self.tree.node_type(parent_ix)
            .expect("Node not part of the tree") != ContainerType::Workspace {
            if let Some(view_ix) = self.tree.descendant_of_type_right(parent_ix,
                                                            ContainerType::View) {
                match self.tree[view_ix]
                                    .get_handle().expect("view had no handle") {
                    Handle::View(view) => view.focus(),
                    _ => panic!("View had an output handle")
                }
                trace!("Active container set to view at {:?}", view_ix);
                let id = self.tree[view_ix].get_id();
                self.set_active_container(id)
                    .expect("Could not set active container");
                return;
            }
            parent_ix = self.tree.ancestor_of_type(parent_ix,
                                                    ContainerType::Container)
                .unwrap_or_else(|| {
                    self.tree.ancestor_of_type(parent_ix, ContainerType::Workspace)
                        .expect("Container was not part of a workspace")
                });
        }
        // If this is reached, parent is workspace
        let container_ix = self.tree.children_of(parent_ix)[0];
        let root_c_children = self.tree.children_of(container_ix);
        if root_c_children.len() > 0 {
            let new_active_ix = self.tree.descendant_of_type(root_c_children[0],
                                                                ContainerType::View)
                .unwrap_or(root_c_children[0]);
            let id = self.tree[new_active_ix].get_id();
            self.set_active_container(id)
                .expect("Could not set active container");
            match self.tree[new_active_ix] {
                Container::View { ref handle, .. } => handle.focus(),
                _ => {}
            };
            return;
        }
        trace!("Active container set to container {:?}", container_ix);
        let id = self.tree[container_ix].get_id();
        self.set_active_container(id)
            .expect("Could not set active container");

        // Update focus to new container
        self.get_active_container().map(|con| match *con {
            Container::View { ref handle, .. } => handle.focus(),
            Container::Container { .. } => WlcView::root().focus(),
            _ => panic!("Active container not view or container!")
        });
    }
}
<|endoftext|>


<commit_before>use std::iter::repeat;
use std::collections::VecDeque;

fn max(a: u32, b: u32) -> u32 { if a > b { a } else { b } }

#[derive(Clone)]
struct Edge {
    vertex: u32,
    weight: f32,
}

impl Edge {
    pub fn new(vertex_: u32, weight_: f32) -> Edge {
        Edge{vertex: vertex_, weight: weight_,}
    }
}

struct Graph {
    nodes: Vec<Vec<Edge>>,
}

impl Graph {
    pub fn new() -> Graph { Graph{nodes: Vec::new(),} }

    pub fn add_edge(&mut self, src: u32, dst: u32, weight: f32) {
        // only works with rust nightly:
        // if (max(src,dst)) > self.nodes.len() as u32 {
        //  self.nodes.resize((max(src, dst) + 1) as usize, Vec::new());
        //}

        let len = self.nodes.len();
        if (max(src, dst)) > len as u32 {
            let new_len = (max(src, dst) + 1) as usize;
            self.nodes.extend(repeat(Vec::new()).take(new_len - len))
        }
        self.nodes[src as usize].push(Edge::new(dst, weight));
    }
    pub fn bfs(&self, src: u32) {
        let mut queue: VecDeque<u32> = VecDeque::new();
        let mut visited: Vec<bool> = Vec::new();

        // only works with rust nightly:
        // visited.resize(self.nodes.len(), false);

        let len = self.nodes.len() as usize;
        visited.extend(repeat(false).take(len));
        queue.push_front(src);

        while let Some(current) = queue.pop_back() {
            if !visited[current as usize] {
                println!("current: {}" , current);
                visited[current as usize] = true;
            }

            for n in &self.nodes[current as usize] {
                let neighbor: u32 = n.vertex;
                if !visited[neighbor as usize] { queue.push_front(neighbor); }
            }
        }
    }
    pub fn dfs(&self, src: u32) {
        let mut current: u32 = src;
        let mut stack: Vec<u32> = Vec::new();
        let mut visited: Vec<bool> = Vec::new();

        // only works with rust nightly:
        // visited.resize(self.nodes.len(), false);

        let len = self.nodes.len() as usize;
        visited.extend(repeat(false).take(len));
        stack.push(current);

        while stack.len() > 0 {
            current = stack[0 as usize];
            stack.remove(0);
            if !visited[current as usize] {
                println!("current: {}" , current);
                visited[current as usize] = true;
            }

            for n in &self.nodes[current as usize] {
                let neighbor: u32 = n.vertex;
                if !visited[neighbor as usize] { stack.push(neighbor); }
            }
        }
    }
}

fn main() {
    let mut g1 = Graph::new();
    g1.add_edge(0, 1, 1.0);
    g1.add_edge(0, 2, 4.0);
    g1.add_edge(1, 0, 1.0);
    g1.add_edge(1, 2, 2.0);
    g1.add_edge(1, 3, 6.0);
    g1.add_edge(2, 0, 4.0);
    g1.add_edge(2, 1, 2.0);
    g1.add_edge(2, 3, 3.0);
    g1.add_edge(3, 1, 6.0);
    g1.add_edge(3, 2, 3.0);
    g1.bfs(0);
    g1.dfs(0);
}<commit_msg>simplfied vec resize<commit_after>use std::iter::repeat;
use std::collections::VecDeque;

fn max(a: u32, b: u32) -> u32 { if a > b { a } else { b } }

#[derive(Clone)]
struct Edge {
    vertex: u32,
    weight: f32,
}

impl Edge {
    pub fn new(vertex_: u32, weight_: f32) -> Edge {
        Edge{vertex: vertex_, weight: weight_,}
    }
}

struct Graph {
    nodes: Vec<Vec<Edge>>,
}

impl Graph {
    pub fn new() -> Graph { Graph{nodes: Vec::new(),} }

    pub fn add_edge(&mut self, src: u32, dst: u32, weight: f32) {
        // only works with rust nightly:
        // if (max(src,dst)) > self.nodes.len() as u32 {
        //  self.nodes.resize((max(src, dst) + 1) as usize, Vec::new());
        //}

        let len = self.nodes.len();
        if (max(src, dst)) > len as u32 {
            let new_len = (max(src, dst) + 1) as usize;
            self.nodes.extend(repeat(Vec::new()).take(new_len - len))
        }
        self.nodes[src as usize].push(Edge::new(dst, weight));
    }
    pub fn bfs(&self, src: u32) {
        let mut queue: VecDeque<u32> = VecDeque::new();
        let len = self.nodes.len() as usize;
        let mut visited = vec![false; len];

        // only works with rust nightly:
        // visited.resize(self.nodes.len(), false);

        queue.push_front(src);

        while let Some(current) = queue.pop_back() {
            if !visited[current as usize] {
                println!("current: {}" , current);
                visited[current as usize] = true;
            }

            for n in &self.nodes[current as usize] {
                let neighbor: u32 = n.vertex;
                if !visited[neighbor as usize] { queue.push_front(neighbor); }
            }
        }
    }
    pub fn dfs(&self, src: u32) {
        let mut current: u32 = src;
        let mut stack: Vec<u32> = Vec::new();
        let mut visited: Vec<bool> = Vec::new();

        // only works with rust nightly:
        // visited.resize(self.nodes.len(), false);

        let len = self.nodes.len() as usize;
        visited.extend(repeat(false).take(len));
        stack.push(current);

        while stack.len() > 0 {
            current = stack[0 as usize];
            stack.remove(0);
            if !visited[current as usize] {
                println!("current: {}" , current);
                visited[current as usize] = true;
            }

            for n in &self.nodes[current as usize] {
                let neighbor: u32 = n.vertex;
                if !visited[neighbor as usize] { stack.push(neighbor); }
            }
        }
    }
}

fn main() {
    let mut g1 = Graph::new();
    g1.add_edge(0, 1, 1.0);
    g1.add_edge(0, 2, 4.0);
    g1.add_edge(1, 0, 1.0);
    g1.add_edge(1, 2, 2.0);
    g1.add_edge(1, 3, 6.0);
    g1.add_edge(2, 0, 4.0);
    g1.add_edge(2, 1, 2.0);
    g1.add_edge(2, 3, 3.0);
    g1.add_edge(3, 1, 6.0);
    g1.add_edge(3, 2, 3.0);
    g1.bfs(0);
    g1.dfs(0);
}<|endoftext|>