<commit_before>/// Struct to represent an inheritable opacity property
/// https://www.w3.org/TR/SVG/masking.html#OpacityProperty

use ::cssparser::{Parser, ParserInput, Token};
use ::libc;

use std::str::FromStr;

use ::glib::translate::*;

use parsers::ParseError;
use error::*;

// Keep this in sync with rsvg-css.h:RsvgOpacityKind
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum OpacityKind {
    Inherit,
    Specified,
    ParseError
}

// Keep this in sync with rsvg-css.h:RsvgOpacitySpec
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct OpacitySpec {
    kind: OpacityKind,
    opacity: u8
}

// This is the Rust version of the above
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Opacity {
    Inherit,
    Specified (f64)
}

impl From<Result<Opacity, AttributeError>> for OpacitySpec {
    fn from (result: Result<Opacity, AttributeError>) -> OpacitySpec {
        match result {
            Ok (Opacity::Inherit) =>
                OpacitySpec {
                    kind: OpacityKind::Inherit,
                    opacity: 0
                },

            Ok (Opacity::Specified (val)) =>
                OpacitySpec {
                    kind: OpacityKind::Specified,
                    opacity: opacity_to_u8 (val)
                },

            _ =>
                OpacitySpec {
                    kind: OpacityKind::ParseError,
                    opacity: 0
                }
        }
    }
}

pub fn opacity_to_u8 (val: f64) -> u8 {
    (val * 255.0 + 0.5).floor () as u8
}

impl FromStr for Opacity {
    type Err = AttributeError;

    fn from_str (s: &str) -> Result<Opacity, AttributeError> {
        let mut input = ParserInput::new (s);
        let mut parser = Parser::new (&mut input);

        let token = parser.next ();
        let result = match token {
            Ok (&Token::Ident (ref value)) => {
                if value.as_ref () == "inherit" {
                    Ok (Opacity::Inherit)
                } else {
                    Err (())
                }
            },

            Ok (&Token::Number { value, .. }) => {
                if value < 0.0 {
                    Ok (Opacity::Specified (0.0))
                } else if value > 1.0 {
                    Ok (Opacity::Specified (1.0))
                } else {
                    Ok (Opacity::Specified (value as f64))
                }
            },

            _ => Err (())
        };

        result.and_then (|opacity|
                         parser.expect_exhausted ()
                         .map (|_| opacity)
                         .map_err (|_| ()))
            .map_err (|_| AttributeError::Parse (ParseError::new ("expected 'inherit' or number")))
    }
}

impl Opacity {
    pub fn from_opacity_spec (spec: &OpacitySpec) -> Result <Opacity, AttributeError> {
        match *spec {
            OpacitySpec { kind: OpacityKind::Inherit, .. }      => Ok (Opacity::Inherit),

            OpacitySpec { kind: OpacityKind::Specified, opacity } => Ok (Opacity::Specified (opacity as f64 / 255.0)),

            OpacitySpec { kind: OpacityKind::ParseError, .. } => Err (AttributeError::Parse (ParseError::new ("parse error")))
        }
    }
}

#[no_mangle]
pub extern fn rsvg_css_parse_opacity (string: *const libc::c_char) -> OpacitySpec {
    let s = unsafe { String::from_glib_none (string) };

    OpacitySpec::from (Opacity::from_str (&s))
}

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

    #[test]
    fn parses_inherit () {
        assert_eq! (Opacity::from_str ("inherit"), Ok (Opacity::Inherit));
    }

    #[test]
    fn parses_number () {
        assert_eq! (Opacity::from_str ("0"),   Ok (Opacity::Specified (0.0)));
        assert_eq! (Opacity::from_str ("1"),   Ok (Opacity::Specified (1.0)));
        assert_eq! (Opacity::from_str ("0.5"), Ok (Opacity::Specified (0.5)));
    }

    #[test]
    fn parses_out_of_range_number () {
        assert_eq! (Opacity::from_str ("-10"), Ok (Opacity::Specified (0.0)));
        assert_eq! (Opacity::from_str ("10"),  Ok (Opacity::Specified (1.0)));
    }

    #[test]
    fn errors_on_invalid_input () {
        assert! (is_parse_error (&Opacity::from_str ("")));
        assert! (is_parse_error (&Opacity::from_str ("foo")));
        assert! (is_parse_error (&Opacity::from_str ("-x")));
    }

    #[test]
    fn errors_on_extra_input () {
        assert! (is_parse_error (&Opacity::from_str ("inherit a million dollars")));
        assert! (is_parse_error (&Opacity::from_str ("0.0foo")));
    }

    fn parse (s: &str) -> OpacitySpec {
        rsvg_css_parse_opacity (s.to_glib_none ().0)
    }

    #[test]
    fn converts_result_to_opacity_spec () {
        assert_eq! (parse ("inherit"),
                    OpacitySpec { kind: OpacityKind::Inherit,
                                  opacity: 0 });

        assert_eq! (parse ("0"),
                    OpacitySpec { kind: OpacityKind::Specified,
                                  opacity: 0 });
        assert_eq! (parse ("1"),
                    OpacitySpec { kind: OpacityKind::Specified,
                                  opacity: 255 });

        assert_eq! (parse ("foo"),
                    OpacitySpec { kind: OpacityKind::ParseError,
                                  opacity: 0 });
    }

    fn test_roundtrip (s: &str) {
        let result = Opacity::from_str (s);
        let result2 = result.clone ();
        let spec = OpacitySpec::from (result2);

        if result.is_ok () {
            assert_eq! (Opacity::from_opacity_spec (&spec), result);
        } else {
            assert! (Opacity::from_opacity_spec (&spec).is_err ());
        }
    }

    #[test]
    fn roundtrips () {
        test_roundtrip ("inherit");
        test_roundtrip ("0");
        test_roundtrip ("1.0");
        test_roundtrip ("chilaquil");
    }
}
<commit_msg>opacity.rs: Refactor to not have Ok() all over the place<commit_after>/// Struct to represent an inheritable opacity property
/// https://www.w3.org/TR/SVG/masking.html#OpacityProperty

use ::cssparser::{Parser, ParserInput, Token};
use ::libc;

use std::str::FromStr;

use ::glib::translate::*;

use parsers::ParseError;
use error::*;

// Keep this in sync with rsvg-css.h:RsvgOpacityKind
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum OpacityKind {
    Inherit,
    Specified,
    ParseError
}

// Keep this in sync with rsvg-css.h:RsvgOpacitySpec
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct OpacitySpec {
    kind: OpacityKind,
    opacity: u8
}

// This is the Rust version of the above
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Opacity {
    Inherit,
    Specified (f64)
}

impl From<Result<Opacity, AttributeError>> for OpacitySpec {
    fn from (result: Result<Opacity, AttributeError>) -> OpacitySpec {
        match result {
            Ok (Opacity::Inherit) =>
                OpacitySpec {
                    kind: OpacityKind::Inherit,
                    opacity: 0
                },

            Ok (Opacity::Specified (val)) =>
                OpacitySpec {
                    kind: OpacityKind::Specified,
                    opacity: opacity_to_u8 (val)
                },

            _ =>
                OpacitySpec {
                    kind: OpacityKind::ParseError,
                    opacity: 0
                }
        }
    }
}

pub fn opacity_to_u8 (val: f64) -> u8 {
    (val * 255.0 + 0.5).floor () as u8
}

fn make_err () -> AttributeError {
    AttributeError::Parse (ParseError::new ("expected 'inherit' or number"))
}

impl FromStr for Opacity {
    type Err = AttributeError;

    fn from_str (s: &str) -> Result<Opacity, AttributeError> {
        let mut input = ParserInput::new (s);
        let mut parser = Parser::new (&mut input);

        let opacity = {
            let token = parser.next ()
                .map_err (|_| make_err ())?;

            match token {
                &Token::Ident (ref value) => {
                    if value.as_ref () == "inherit" {
                        Opacity::Inherit
                    } else {
                        return Err (make_err ());
                    }
                },

                &Token::Number { value, .. } => {
                    if value < 0.0 {
                        Opacity::Specified (0.0)
                    } else if value > 1.0 {
                        Opacity::Specified (1.0)
                    } else {
                        Opacity::Specified (value as f64)
                    }
                },

                _ => return Err (make_err ())
            }
        };

        parser.expect_exhausted ().map_err (|_| make_err ())?;

        Ok (opacity)
    }
}

impl Opacity {
    pub fn from_opacity_spec (spec: &OpacitySpec) -> Result <Opacity, AttributeError> {
        match *spec {
            OpacitySpec { kind: OpacityKind::Inherit, .. }      => Ok (Opacity::Inherit),

            OpacitySpec { kind: OpacityKind::Specified, opacity } => Ok (Opacity::Specified (opacity as f64 / 255.0)),

            OpacitySpec { kind: OpacityKind::ParseError, .. } => Err (AttributeError::Parse (ParseError::new ("parse error")))
        }
    }
}

#[no_mangle]
pub extern fn rsvg_css_parse_opacity (string: *const libc::c_char) -> OpacitySpec {
    let s = unsafe { String::from_glib_none (string) };

    OpacitySpec::from (Opacity::from_str (&s))
}

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

    #[test]
    fn parses_inherit () {
        assert_eq! (Opacity::from_str ("inherit"), Ok (Opacity::Inherit));
    }

    #[test]
    fn parses_number () {
        assert_eq! (Opacity::from_str ("0"),   Ok (Opacity::Specified (0.0)));
        assert_eq! (Opacity::from_str ("1"),   Ok (Opacity::Specified (1.0)));
        assert_eq! (Opacity::from_str ("0.5"), Ok (Opacity::Specified (0.5)));
    }

    #[test]
    fn parses_out_of_range_number () {
        assert_eq! (Opacity::from_str ("-10"), Ok (Opacity::Specified (0.0)));
        assert_eq! (Opacity::from_str ("10"),  Ok (Opacity::Specified (1.0)));
    }

    #[test]
    fn errors_on_invalid_input () {
        assert! (is_parse_error (&Opacity::from_str ("")));
        assert! (is_parse_error (&Opacity::from_str ("foo")));
        assert! (is_parse_error (&Opacity::from_str ("-x")));
    }

    #[test]
    fn errors_on_extra_input () {
        assert! (is_parse_error (&Opacity::from_str ("inherit a million dollars")));
        assert! (is_parse_error (&Opacity::from_str ("0.0foo")));
    }

    fn parse (s: &str) -> OpacitySpec {
        rsvg_css_parse_opacity (s.to_glib_none ().0)
    }

    #[test]
    fn converts_result_to_opacity_spec () {
        assert_eq! (parse ("inherit"),
                    OpacitySpec { kind: OpacityKind::Inherit,
                                  opacity: 0 });

        assert_eq! (parse ("0"),
                    OpacitySpec { kind: OpacityKind::Specified,
                                  opacity: 0 });
        assert_eq! (parse ("1"),
                    OpacitySpec { kind: OpacityKind::Specified,
                                  opacity: 255 });

        assert_eq! (parse ("foo"),
                    OpacitySpec { kind: OpacityKind::ParseError,
                                  opacity: 0 });
    }

    fn test_roundtrip (s: &str) {
        let result = Opacity::from_str (s);
        let result2 = result.clone ();
        let spec = OpacitySpec::from (result2);

        if result.is_ok () {
            assert_eq! (Opacity::from_opacity_spec (&spec), result);
        } else {
            assert! (Opacity::from_opacity_spec (&spec).is_err ());
        }
    }

    #[test]
    fn roundtrips () {
        test_roundtrip ("inherit");
        test_roundtrip ("0");
        test_roundtrip ("1.0");
        test_roundtrip ("chilaquil");
    }
}
<|endoftext|>


<commit_before>static ABC: &'static str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
use std::ascii::AsciiExt;

pub fn get_diamond(diamond_char: char) -> Vec<String> {
    let mut result: Vec<String> = Vec::new();
    let diamond_char = AsciiExt::to_ascii_uppercase(&diamond_char);
    if ABC.find(diamond_char).is_none() {
        return result;
    }
    if diamond_char == 'A' {
        return vec![String::from("A")];
    }

    //build first half
    for char_in_abc in ABC.chars() {
        result.push(get_line(char_in_abc, diamond_char).clone());
        if char_in_abc == diamond_char {
            break;
        }
    }

    //build second half
    let mut rev = result.clone();
    rev.pop(); //remove middle pice to avoid duplicates
    for line in rev.drain(..).rev() {
        result.push(line);

    }

    result
}

fn get_line(char_in_abc: char, diamond_char: char) -> String {
    let mut r = String::new();
    let letter_e = get_letter_line(char_in_abc);
    let letter_c = get_letter_line(diamond_char);
    let ws = letter_c.len() - letter_e.len(); //number of whitespaces

    //left
    for _ in 0..ws / 2 {
        r.push(' ');
    }
    //letter line
    for i in letter_e.chars() {
        r.push(i)
    }
    //right
    for _ in 0..ws / 2 {
        r.push(' ');
    }
    r
}

fn get_letter_line(char_in_abc: char) -> String {
    let mut r = String::new();
    let odd = (0..)
        .filter(|x| x % 2 != 0)
        .nth(ABC.find(char_in_abc).unwrap())
        .unwrap();
    for i in 0..odd {
        if i == 0 || i == odd - 1 {
            r.push(char_in_abc);
        } else {
            r.push(' ');
        }
    }
    r
}
<commit_msg>Fix rustc 1.26 warnings<commit_after>static ABC: &'static str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

pub fn get_diamond(diamond_char: char) -> Vec<String> {
    let mut result: Vec<String> = Vec::new();
    let diamond_char = diamond_char.to_ascii_uppercase();
    if ABC.find(diamond_char).is_none() {
        return result;
    }
    if diamond_char == 'A' {
        return vec![String::from("A")];
    }

    //build first half
    for char_in_abc in ABC.chars() {
        result.push(get_line(char_in_abc, diamond_char).clone());
        if char_in_abc == diamond_char {
            break;
        }
    }

    //build second half
    let mut rev = result.clone();
    rev.pop(); //remove middle pice to avoid duplicates
    for line in rev.drain(..).rev() {
        result.push(line);
    }

    result
}

fn get_line(char_in_abc: char, diamond_char: char) -> String {
    let mut r = String::new();
    let letter_e = get_letter_line(char_in_abc);
    let letter_c = get_letter_line(diamond_char);
    let ws = letter_c.len() - letter_e.len(); //number of whitespaces

    //left
    for _ in 0..ws / 2 {
        r.push(' ');
    }
    //letter line
    for i in letter_e.chars() {
        r.push(i)
    }
    //right
    for _ in 0..ws / 2 {
        r.push(' ');
    }
    r
}

fn get_letter_line(char_in_abc: char) -> String {
    let mut r = String::new();
    let odd = (0..)
        .filter(|x| x % 2 != 0)
        .nth(ABC.find(char_in_abc).unwrap())
        .unwrap();
    for i in 0..odd {
        if i == 0 || i == odd - 1 {
            r.push(char_in_abc);
        } else {
            r.push(' ');
        }
    }
    r
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use std::time::Instant;
use std::mem;
use std::hash::Hash;

use timely::dataflow::*;

use differential_dataflow::lattice::Lattice;
use differential_dataflow::input::Input;
use differential_dataflow::Collection;
use differential_dataflow::operators::*;
use differential_dataflow::operators::arrange::ArrangeByKey;

use differential_dataflow::trace::implementations::ord::OrdValSpine as DefaultValTrace;
use differential_dataflow::operators::arrange::TraceAgent;
use differential_dataflow::operators::arrange::Arranged;
use differential_dataflow::operators::iterate::Variable;

type Arrange<G, K, V, R> = Arranged<G, K, V, R, TraceAgent<K, V, <G as ScopeParent>::Timestamp, R, DefaultValTrace<K, V, <G as ScopeParent>::Timestamp, R>>>;

type Node = u32;
type Edge = (Node, Node);
type Iter = u32;
type Diff = i32;

fn main() {

    // snag a filename to use for the input graph.
    let filename = std::env::args().nth(1).unwrap();
    let program = std::env::args().nth(2).unwrap();
    let inspect = std::env::args().any(|x| x == "inspect");

    timely::execute_from_args(std::env::args().skip(1), move |worker| {

        let peers = worker.peers();
        let index = worker.index();

        let mut input = worker.dataflow::<(),_,_>(|scope| {

            let (input, graph) = scope.new_collection();

            // each edge should exist in both directions.
            let graph = graph.arrange_by_key();

            match program.as_str() {
                "tc"    => tc(&graph).filter(move |_| inspect).map(|_| ()).consolidate().inspect(|x| println!("tc count: {:?}", x)).probe(),
                // "sc"    => _strongly_connected(&graph.as_collection(|k,v| (*k,*v))).filter(move |_| inspect).map(|_| ()).consolidate().inspect(|x| println!("tc count: {:?}", x)).probe(),
                "sg"    => sg(&graph).filter(move |_| inspect).map(|_| ()).consolidate().inspect(|x| println!("sg count: {:?}", x)).probe(),
                _       => panic!("must specify one of 'tc', 'sg'.")
            };

            input
        });

        let timer = Instant::now();

        let mut nodes = 0;

        use std::io::{BufReader, BufRead};
        use std::fs::File;

        let file = BufReader::new(File::open(filename.clone()).unwrap());
        for (count, readline) in file.lines().enumerate() {
            let line = readline.ok().expect("read error");
            if count % peers == index && !line.starts_with('#') {
                let mut elts = line[..].split_whitespace();
                let src: u32 = elts.next().unwrap().parse().ok().expect("malformed src");
                let dst: u32 = elts.next().unwrap().parse().ok().expect("malformed dst");
                if nodes < src { nodes = src; }
                if nodes < dst { nodes = dst; }
                input.update((src, dst), 1);
            }
        }

        if index == 0 { println!("{:?}\tData ingested", timer.elapsed()); }

        input.close();
        while worker.step() { }

        if index == 0 { println!("{:?}\tComputation complete", timer.elapsed()); }

    }).unwrap();
}

use timely::progress::nested::product::Product;
use timely::progress::timestamp::RootTimestamp;

fn _trim_and_flip<G: Scope>(graph: &Collection<G, Edge>) -> Collection<G, Edge>
where G::Timestamp: Lattice+Ord+Hash {
    graph.iterate(|edges| {
        // keep edges from active edge destinations.
        let active = edges.map(|(src,_dst)| src)
                          .distinct();

        graph.enter(&edges.scope())
             .arrange_by_key()
             .semijoin(&active)
    })
    .map_in_place(|x| mem::swap(&mut x.0, &mut x.1))
}

fn _strongly_connected<G: Scope>(graph: &Collection<G, Edge>) -> Collection<G, Edge>
where G::Timestamp: Lattice+Ord+Hash {
    graph.iterate(|inner| {
        let edges = graph.enter(&inner.scope());
        let trans = edges.map_in_place(|x| mem::swap(&mut x.0, &mut x.1));
        _trim_edges(&_trim_edges(inner, &edges), &trans)
    })
}

fn _trim_edges<G: Scope>(cycle: &Collection<G, Edge>, edges: &Collection<G, Edge>)
    -> Collection<G, Edge> where G::Timestamp: Lattice+Ord+Hash {

    let nodes = edges.map_in_place(|x| x.0 = x.1)
                     .consolidate();

    let labels = _reachability(&cycle, &nodes);

    edges.join_map(&labels, |&e1,&e2,&l1| (e2,(e1,l1)))
         .join_map(&labels, |&e2,&(e1,l1),&l2| ((e1,e2),(l1,l2)))
         .filter(|&(_,(l1,l2))| l1 == l2)
         .map(|((x1,x2),_)| (x2,x1))
}

fn _reachability<G: Scope>(edges: &Collection<G, Edge>, nodes: &Collection<G, (Node, Node)>) -> Collection<G, Edge>
where G::Timestamp: Lattice+Ord+Hash {

    edges.filter(|_| false)
         .iterate(|inner| {
             let edges = edges.enter(&inner.scope());
             let nodes = nodes.enter_at(&inner.scope(), |r| 256 * (64 - (r.0 as u64).leading_zeros() as u64));

             inner.join_map(&edges, |_k,l,d| (*d,*l))
                  .concat(&nodes)
                  .group(|_, s, t| t.push((*s[0].0, 1)))

         })
}

// returns pairs (n, s) indicating node n can be reached from a root in s steps.
fn tc<G: Scope<Timestamp=Product<RootTimestamp, ()>>>(edges: &Arrange<G, Node, Node, Diff>) -> Collection<G, Edge, Diff> {

    // repeatedly update minimal distances each node can be reached from each root
    edges.stream.scope().scoped(|scope| {

            let inner = Variable::new(scope, Iter::max_value(), 1);
            let edges = edges.enter(&inner.scope());

            let result =
            inner
                .map(|(x,y)| (y,x))
                .join_core(&edges, |_y,&x,&z| Some((x, z)))
                .concat(&edges.as_collection(|&k,&v| (k,v)))
                .threshold_total(|_| 1);

            inner.set(&result);
            result.leave()
        }
    )
}

// returns pairs (n, s) indicating node n can be reached from a root in s steps.
fn sg<G: Scope<Timestamp=Product<RootTimestamp, ()>>>(edges: &Arrange<G, Node, Node, Diff>) -> Collection<G, Edge, Diff> {

    let peers = edges.join_core(&edges, |_,&x,&y| Some((x,y))).filter(|&(x,y)| x != y);

    // repeatedly update minimal distances each node can be reached from each root
    peers.scope().scoped(|scope| {

            let inner = Variable::new(scope, Iter::max_value(), 1);
            let edges = edges.enter(&inner.scope());
            let peers = peers.enter(&inner.scope());

            let result =
            inner
                .join_core(&edges, |_,&x,&z| Some((x, z)))
                .join_core(&edges, |_,&x,&z| Some((x, z)))
                .concat(&peers)
                .threshold_total(|_| 1);

            inner.set(&result);
            result.leave()
        }
    )
}<commit_msg>flexible types<commit_after>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use std::time::Instant;
use std::mem;
use std::hash::Hash;

use timely::dataflow::*;

use differential_dataflow::lattice::Lattice;
use differential_dataflow::input::Input;
use differential_dataflow::Collection;
use differential_dataflow::operators::*;
use differential_dataflow::operators::arrange::ArrangeByKey;

use differential_dataflow::trace::implementations::ord::OrdValSpine as DefaultValTrace;
use differential_dataflow::operators::arrange::TraceAgent;
use differential_dataflow::operators::arrange::Arranged;
use differential_dataflow::operators::iterate::Variable;

type Arrange<G, K, V, R> = Arranged<G, K, V, R, TraceAgent<K, V, <G as ScopeParent>::Timestamp, R, DefaultValTrace<K, V, <G as ScopeParent>::Timestamp, R>>>;

type Node = u32;
type Edge = (Node, Node);
type Iter = u32;
type Diff = i32;

fn main() {

    // snag a filename to use for the input graph.
    let filename = std::env::args().nth(1).unwrap();
    let program = std::env::args().nth(2).unwrap();
    let inspect = std::env::args().any(|x| x == "inspect");

    timely::execute_from_args(std::env::args().skip(1), move |worker| {

        let peers = worker.peers();
        let index = worker.index();
        let timer = Instant::now();

        let core_ids = core_affinity::get_core_ids().unwrap();
        core_affinity::set_for_current(core_ids[index % core_ids.len()]);

        let mut input = worker.dataflow::<(),_,_>(|scope| {

            let (input, graph) = scope.new_collection();

            // each edge should exist in both directions.
            let graph = graph.arrange_by_key();

            match program.as_str() {
                "tc"    => tc(&graph).filter(move |_| inspect).map(|_| ()).consolidate().inspect(|x| println!("tc count: {:?}", x)).probe(),
                // "sc"    => _strongly_connected(&graph.as_collection(|k,v| (*k,*v))).filter(move |_| inspect).map(|_| ()).consolidate().inspect(|x| println!("tc count: {:?}", x)).probe(),
                "sg"    => sg(&graph).filter(move |_| inspect).map(|_| ()).consolidate().inspect(|x| println!("sg count: {:?}", x)).probe(),
                _       => panic!("must specify one of 'tc', 'sg'.")
            };

            input
        });

        let mut nodes = 0;

        use std::io::{BufReader, BufRead};
        use std::fs::File;

        let file = BufReader::new(File::open(filename.clone()).unwrap());
        for (count, readline) in file.lines().enumerate() {
            let line = readline.ok().expect("read error");
            if count % peers == index && !line.starts_with('#') {
                let mut elts = line[..].split_whitespace();
                let src: u32 = elts.next().unwrap().parse().ok().expect("malformed src");
                let dst: u32 = elts.next().unwrap().parse().ok().expect("malformed dst");
                if nodes < src { nodes = src; }
                if nodes < dst { nodes = dst; }
                input.update((src, dst), 1);
            }
        }

        if index == 0 { println!("{:?}\tData ingested", timer.elapsed()); }

        input.close();
        while worker.step() { }

        if index == 0 { println!("{:?}\tComputation complete", timer.elapsed()); }

    }).unwrap();
}

use timely::progress::nested::product::Product;
use timely::progress::timestamp::RootTimestamp;

fn _trim_and_flip<G: Scope>(graph: &Collection<G, Edge>) -> Collection<G, Edge>
where G::Timestamp: Lattice+Ord+Hash {
    graph.iterate(|edges| {
        // keep edges from active edge destinations.
        let active = edges.map(|(src,_dst)| src)
                          .distinct();

        graph.enter(&edges.scope())
             .arrange_by_key()
             .semijoin(&active)
    })
    .map_in_place(|x| mem::swap(&mut x.0, &mut x.1))
}

fn _strongly_connected<G: Scope>(graph: &Collection<G, Edge>) -> Collection<G, Edge>
where G::Timestamp: Lattice+Ord+Hash {
    graph.iterate(|inner| {
        let edges = graph.enter(&inner.scope());
        let trans = edges.map_in_place(|x| mem::swap(&mut x.0, &mut x.1));
        _trim_edges(&_trim_edges(inner, &edges), &trans)
    })
}

fn _trim_edges<G: Scope>(cycle: &Collection<G, Edge>, edges: &Collection<G, Edge>)
    -> Collection<G, Edge> where G::Timestamp: Lattice+Ord+Hash {

    let nodes = edges.map_in_place(|x| x.0 = x.1)
                     .consolidate();

    let labels = _reachability(&cycle, &nodes);

    edges.join_map(&labels, |&e1,&e2,&l1| (e2,(e1,l1)))
         .join_map(&labels, |&e2,&(e1,l1),&l2| ((e1,e2),(l1,l2)))
         .filter(|&(_,(l1,l2))| l1 == l2)
         .map(|((x1,x2),_)| (x2,x1))
}

fn _reachability<G: Scope>(edges: &Collection<G, Edge>, nodes: &Collection<G, (Node, Node)>) -> Collection<G, Edge>
where G::Timestamp: Lattice+Ord+Hash {

    edges.filter(|_| false)
         .iterate(|inner| {
             let edges = edges.enter(&inner.scope());
             let nodes = nodes.enter_at(&inner.scope(), |r| 256 * (64 - (r.0 as u64).leading_zeros() as u64));

             inner.join_map(&edges, |_k,l,d| (*d,*l))
                  .concat(&nodes)
                  .group(|_, s, t| t.push((*s[0].0, 1)))

         })
}

// returns pairs (n, s) indicating node n can be reached from a root in s steps.
fn tc<G: Scope<Timestamp=Product<RootTimestamp, ()>>>(edges: &Arrange<G, Node, Node, Diff>) -> Collection<G, Edge, Diff> {

    // repeatedly update minimal distances each node can be reached from each root
    edges.stream.scope().scoped(|scope| {

            let inner = Variable::new(scope, Iter::max_value(), 1);
            let edges = edges.enter(&inner.scope());

            let result =
            inner
                .map(|(x,y)| (y,x))
                .join_core(&edges, |_y,&x,&z| Some((x, z)))
                .concat(&edges.as_collection(|&k,&v| (k,v)))
                .threshold_total(|_| 1);

            inner.set(&result);
            result.leave()
        }
    )
}

// returns pairs (n, s) indicating node n can be reached from a root in s steps.
fn sg<G: Scope<Timestamp=Product<RootTimestamp, ()>>>(edges: &Arrange<G, Node, Node, Diff>) -> Collection<G, Edge, Diff> {

    let peers = edges.join_core(&edges, |_,&x,&y| Some((x,y))).filter(|&(x,y)| x != y);

    // repeatedly update minimal distances each node can be reached from each root
    peers.scope().scoped(|scope| {

            let inner = Variable::new(scope, Iter::max_value(), 1);
            let edges = edges.enter(&inner.scope());
            let peers = peers.enter(&inner.scope());

            let result =
            inner
                .join_core(&edges, |_,&x,&z| Some((x, z)))
                .join_core(&edges, |_,&x,&z| Some((x, z)))
                .concat(&peers)
                .threshold_total(|_| 1);

            inner.set(&result);
            result.leave()
        }
    )
}<|endoftext|>


<commit_before>//! Defines `Body`: a lowered representation of bodies of functions, statics and
//! consts.
mod lower;
pub mod scope;

use std::{mem, ops::Index, sync::Arc};

use drop_bomb::DropBomb;
use either::Either;
use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroDefId};
use ra_arena::{map::ArenaMap, Arena};
use ra_cfg::CfgOptions;
use ra_db::CrateId;
use ra_prof::profile;
use ra_syntax::{ast, AstNode, AstPtr};
use rustc_hash::FxHashMap;

use crate::{
    attr::Attrs,
    db::DefDatabase,
    expr::{Expr, ExprId, Pat, PatId},
    item_scope::BuiltinShadowMode,
    item_scope::ItemScope,
    nameres::CrateDefMap,
    path::{ModPath, Path},
    src::HasSource,
    AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId,
};

/// A subser of Exander that only deals with cfg attributes. We only need it to
/// avoid cyclic queries in crate def map during enum processing.
pub(crate) struct CfgExpander {
    cfg_options: CfgOptions,
    hygiene: Hygiene,
}

pub(crate) struct Expander {
    cfg_expander: CfgExpander,
    crate_def_map: Arc<CrateDefMap>,
    current_file_id: HirFileId,
    ast_id_map: Arc<AstIdMap>,
    module: ModuleId,
    recursive_limit: usize,
}

impl CfgExpander {
    pub(crate) fn new(
        db: &dyn DefDatabase,
        current_file_id: HirFileId,
        krate: CrateId,
    ) -> CfgExpander {
        let hygiene = Hygiene::new(db.upcast(), current_file_id);
        let cfg_options = db.crate_graph()[krate].cfg_options.clone();
        CfgExpander { cfg_options, hygiene }
    }

    pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs {
        Attrs::new(owner, &self.hygiene)
    }

    pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
        attrs.is_cfg_enabled(&self.cfg_options)
    }
}

impl Expander {
    pub(crate) fn new(
        db: &dyn DefDatabase,
        current_file_id: HirFileId,
        module: ModuleId,
    ) -> Expander {
        let cfg_expander = CfgExpander::new(db, current_file_id, module.krate);
        let crate_def_map = db.crate_def_map(module.krate);
        let ast_id_map = db.ast_id_map(current_file_id);
        Expander {
            cfg_expander,
            crate_def_map,
            current_file_id,
            ast_id_map,
            module,
            recursive_limit: 0,
        }
    }

    pub(crate) fn enter_expand<T: ast::AstNode>(
        &mut self,
        db: &dyn DefDatabase,
        local_scope: Option<&ItemScope>,
        macro_call: ast::MacroCall,
    ) -> Option<(Mark, T)> {
        if self.recursive_limit > 1024 {
            return None;
        }

        let macro_call = InFile::new(self.current_file_id, &macro_call);

        if let Some(call_id) = macro_call.as_call_id(db, |path| {
            if let Some(local_scope) = local_scope {
                if let Some(def) = path.as_ident().and_then(|n| local_scope.get_legacy_macro(n)) {
                    return Some(def);
                }
            }
            self.resolve_path_as_macro(db, &path)
        }) {
            let file_id = call_id.as_file();
            if let Some(node) = db.parse_or_expand(file_id) {
                if let Some(expr) = T::cast(node) {
                    log::debug!("macro expansion {:#?}", expr.syntax());

                    let mark = Mark {
                        file_id: self.current_file_id,
                        ast_id_map: mem::take(&mut self.ast_id_map),
                        bomb: DropBomb::new("expansion mark dropped"),
                    };
                    self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id);
                    self.current_file_id = file_id;
                    self.ast_id_map = db.ast_id_map(file_id);
                    self.recursive_limit += 1;

                    return Some((mark, expr));
                }
            }
        }

        // FIXME: Instead of just dropping the error from expansion
        // report it
        None
    }

    pub(crate) fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) {
        self.cfg_expander.hygiene = Hygiene::new(db.upcast(), mark.file_id);
        self.current_file_id = mark.file_id;
        self.ast_id_map = mem::take(&mut mark.ast_id_map);
        self.recursive_limit -= 1;
        mark.bomb.defuse();
    }

    pub(crate) fn to_source<T>(&self, value: T) -> InFile<T> {
        InFile { file_id: self.current_file_id, value }
    }

    pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs {
        self.cfg_expander.parse_attrs(owner)
    }

    pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
        self.cfg_expander.is_cfg_enabled(attrs)
    }

    fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
        Path::from_src(path, &self.cfg_expander.hygiene)
    }

    fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> {
        self.crate_def_map
            .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other)
            .0
            .take_macros()
    }

    fn ast_id<N: AstNode>(&self, item: &N) -> AstId<N> {
        let file_local_id = self.ast_id_map.ast_id(item);
        AstId::new(self.current_file_id, file_local_id)
    }
}

pub(crate) struct Mark {
    file_id: HirFileId,
    ast_id_map: Arc<AstIdMap>,
    bomb: DropBomb,
}

/// The body of an item (function, const etc.).
#[derive(Debug, Eq, PartialEq)]
pub struct Body {
    pub exprs: Arena<Expr>,
    pub pats: Arena<Pat>,
    /// The patterns for the function's parameters. While the parameter types are
    /// part of the function signature, the patterns are not (they don't change
    /// the external type of the function).
    ///
    /// If this `Body` is for the body of a constant, this will just be
    /// empty.
    pub params: Vec<PatId>,
    /// The `ExprId` of the actual body expression.
    pub body_expr: ExprId,
    pub item_scope: ItemScope,
}

pub type ExprPtr = AstPtr<ast::Expr>;
pub type ExprSource = InFile<ExprPtr>;

pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
pub type PatSource = InFile<PatPtr>;

/// An item body together with the mapping from syntax nodes to HIR expression
/// IDs. This is needed to go from e.g. a position in a file to the HIR
/// expression containing it; but for type inference etc., we want to operate on
/// a structure that is agnostic to the actual positions of expressions in the
/// file, so that we don't recompute types whenever some whitespace is typed.
///
/// One complication here is that, due to macro expansion, a single `Body` might
/// be spread across several files. So, for each ExprId and PatId, we record
/// both the HirFileId and the position inside the file. However, we only store
/// AST -> ExprId mapping for non-macro files, as it is not clear how to handle
/// this properly for macros.
#[derive(Default, Debug, Eq, PartialEq)]
pub struct BodySourceMap {
    expr_map: FxHashMap<ExprSource, ExprId>,
    expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>,
    pat_map: FxHashMap<PatSource, PatId>,
    pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>,
    field_map: FxHashMap<(ExprId, usize), InFile<AstPtr<ast::RecordField>>>,
    expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>,
}

#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
pub struct SyntheticSyntax;

impl Body {
    pub(crate) fn body_with_source_map_query(
        db: &dyn DefDatabase,
        def: DefWithBodyId,
    ) -> (Arc<Body>, Arc<BodySourceMap>) {
        let _p = profile("body_with_source_map_query");
        let mut params = None;

        let (file_id, module, body) = match def {
            DefWithBodyId::FunctionId(f) => {
                let f = f.lookup(db);
                let src = f.source(db);
                params = src.value.param_list();
                (src.file_id, f.module(db), src.value.body().map(ast::Expr::from))
            }
            DefWithBodyId::ConstId(c) => {
                let c = c.lookup(db);
                let src = c.source(db);
                (src.file_id, c.module(db), src.value.body())
            }
            DefWithBodyId::StaticId(s) => {
                let s = s.lookup(db);
                let src = s.source(db);
                (src.file_id, s.module(db), src.value.body())
            }
        };
        let expander = Expander::new(db, file_id, module);
        let (body, source_map) = Body::new(db, def, expander, params, body);
        (Arc::new(body), Arc::new(source_map))
    }

    pub(crate) fn body_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<Body> {
        db.body_with_source_map(def).0
    }

    fn new(
        db: &dyn DefDatabase,
        def: DefWithBodyId,
        expander: Expander,
        params: Option<ast::ParamList>,
        body: Option<ast::Expr>,
    ) -> (Body, BodySourceMap) {
        lower::lower(db, def, expander, params, body)
    }
}

impl Index<ExprId> for Body {
    type Output = Expr;

    fn index(&self, expr: ExprId) -> &Expr {
        &self.exprs[expr]
    }
}

impl Index<PatId> for Body {
    type Output = Pat;

    fn index(&self, pat: PatId) -> &Pat {
        &self.pats[pat]
    }
}

impl BodySourceMap {
    pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> {
        self.expr_map_back[expr].clone()
    }

    pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprId> {
        let src = node.map(|it| AstPtr::new(it));
        self.expr_map.get(&src).cloned()
    }

    pub fn node_macro_file(&self, node: InFile<&ast::MacroCall>) -> Option<HirFileId> {
        let src = node.map(|it| AstPtr::new(it));
        self.expansions.get(&src).cloned()
    }

    pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> {
        self.pat_map_back[pat].clone()
    }

    pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<PatId> {
        let src = node.map(|it| Either::Left(AstPtr::new(it)));
        self.pat_map.get(&src).cloned()
    }

    pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordField>> {
        self.field_map[&(expr, field)].clone()
    }
}
<commit_msg>Fix typo<commit_after>//! Defines `Body`: a lowered representation of bodies of functions, statics and
//! consts.
mod lower;
pub mod scope;

use std::{mem, ops::Index, sync::Arc};

use drop_bomb::DropBomb;
use either::Either;
use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroDefId};
use ra_arena::{map::ArenaMap, Arena};
use ra_cfg::CfgOptions;
use ra_db::CrateId;
use ra_prof::profile;
use ra_syntax::{ast, AstNode, AstPtr};
use rustc_hash::FxHashMap;

use crate::{
    attr::Attrs,
    db::DefDatabase,
    expr::{Expr, ExprId, Pat, PatId},
    item_scope::BuiltinShadowMode,
    item_scope::ItemScope,
    nameres::CrateDefMap,
    path::{ModPath, Path},
    src::HasSource,
    AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId,
};

/// A subset of Exander that only deals with cfg attributes. We only need it to
/// avoid cyclic queries in crate def map during enum processing.
pub(crate) struct CfgExpander {
    cfg_options: CfgOptions,
    hygiene: Hygiene,
}

pub(crate) struct Expander {
    cfg_expander: CfgExpander,
    crate_def_map: Arc<CrateDefMap>,
    current_file_id: HirFileId,
    ast_id_map: Arc<AstIdMap>,
    module: ModuleId,
    recursive_limit: usize,
}

impl CfgExpander {
    pub(crate) fn new(
        db: &dyn DefDatabase,
        current_file_id: HirFileId,
        krate: CrateId,
    ) -> CfgExpander {
        let hygiene = Hygiene::new(db.upcast(), current_file_id);
        let cfg_options = db.crate_graph()[krate].cfg_options.clone();
        CfgExpander { cfg_options, hygiene }
    }

    pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs {
        Attrs::new(owner, &self.hygiene)
    }

    pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
        attrs.is_cfg_enabled(&self.cfg_options)
    }
}

impl Expander {
    pub(crate) fn new(
        db: &dyn DefDatabase,
        current_file_id: HirFileId,
        module: ModuleId,
    ) -> Expander {
        let cfg_expander = CfgExpander::new(db, current_file_id, module.krate);
        let crate_def_map = db.crate_def_map(module.krate);
        let ast_id_map = db.ast_id_map(current_file_id);
        Expander {
            cfg_expander,
            crate_def_map,
            current_file_id,
            ast_id_map,
            module,
            recursive_limit: 0,
        }
    }

    pub(crate) fn enter_expand<T: ast::AstNode>(
        &mut self,
        db: &dyn DefDatabase,
        local_scope: Option<&ItemScope>,
        macro_call: ast::MacroCall,
    ) -> Option<(Mark, T)> {
        if self.recursive_limit > 1024 {
            return None;
        }

        let macro_call = InFile::new(self.current_file_id, &macro_call);

        if let Some(call_id) = macro_call.as_call_id(db, |path| {
            if let Some(local_scope) = local_scope {
                if let Some(def) = path.as_ident().and_then(|n| local_scope.get_legacy_macro(n)) {
                    return Some(def);
                }
            }
            self.resolve_path_as_macro(db, &path)
        }) {
            let file_id = call_id.as_file();
            if let Some(node) = db.parse_or_expand(file_id) {
                if let Some(expr) = T::cast(node) {
                    log::debug!("macro expansion {:#?}", expr.syntax());

                    let mark = Mark {
                        file_id: self.current_file_id,
                        ast_id_map: mem::take(&mut self.ast_id_map),
                        bomb: DropBomb::new("expansion mark dropped"),
                    };
                    self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id);
                    self.current_file_id = file_id;
                    self.ast_id_map = db.ast_id_map(file_id);
                    self.recursive_limit += 1;

                    return Some((mark, expr));
                }
            }
        }

        // FIXME: Instead of just dropping the error from expansion
        // report it
        None
    }

    pub(crate) fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) {
        self.cfg_expander.hygiene = Hygiene::new(db.upcast(), mark.file_id);
        self.current_file_id = mark.file_id;
        self.ast_id_map = mem::take(&mut mark.ast_id_map);
        self.recursive_limit -= 1;
        mark.bomb.defuse();
    }

    pub(crate) fn to_source<T>(&self, value: T) -> InFile<T> {
        InFile { file_id: self.current_file_id, value }
    }

    pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs {
        self.cfg_expander.parse_attrs(owner)
    }

    pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
        self.cfg_expander.is_cfg_enabled(attrs)
    }

    fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
        Path::from_src(path, &self.cfg_expander.hygiene)
    }

    fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> {
        self.crate_def_map
            .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other)
            .0
            .take_macros()
    }

    fn ast_id<N: AstNode>(&self, item: &N) -> AstId<N> {
        let file_local_id = self.ast_id_map.ast_id(item);
        AstId::new(self.current_file_id, file_local_id)
    }
}

pub(crate) struct Mark {
    file_id: HirFileId,
    ast_id_map: Arc<AstIdMap>,
    bomb: DropBomb,
}

/// The body of an item (function, const etc.).
#[derive(Debug, Eq, PartialEq)]
pub struct Body {
    pub exprs: Arena<Expr>,
    pub pats: Arena<Pat>,
    /// The patterns for the function's parameters. While the parameter types are
    /// part of the function signature, the patterns are not (they don't change
    /// the external type of the function).
    ///
    /// If this `Body` is for the body of a constant, this will just be
    /// empty.
    pub params: Vec<PatId>,
    /// The `ExprId` of the actual body expression.
    pub body_expr: ExprId,
    pub item_scope: ItemScope,
}

pub type ExprPtr = AstPtr<ast::Expr>;
pub type ExprSource = InFile<ExprPtr>;

pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
pub type PatSource = InFile<PatPtr>;

/// An item body together with the mapping from syntax nodes to HIR expression
/// IDs. This is needed to go from e.g. a position in a file to the HIR
/// expression containing it; but for type inference etc., we want to operate on
/// a structure that is agnostic to the actual positions of expressions in the
/// file, so that we don't recompute types whenever some whitespace is typed.
///
/// One complication here is that, due to macro expansion, a single `Body` might
/// be spread across several files. So, for each ExprId and PatId, we record
/// both the HirFileId and the position inside the file. However, we only store
/// AST -> ExprId mapping for non-macro files, as it is not clear how to handle
/// this properly for macros.
#[derive(Default, Debug, Eq, PartialEq)]
pub struct BodySourceMap {
    expr_map: FxHashMap<ExprSource, ExprId>,
    expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>,
    pat_map: FxHashMap<PatSource, PatId>,
    pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>,
    field_map: FxHashMap<(ExprId, usize), InFile<AstPtr<ast::RecordField>>>,
    expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>,
}

#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
pub struct SyntheticSyntax;

impl Body {
    pub(crate) fn body_with_source_map_query(
        db: &dyn DefDatabase,
        def: DefWithBodyId,
    ) -> (Arc<Body>, Arc<BodySourceMap>) {
        let _p = profile("body_with_source_map_query");
        let mut params = None;

        let (file_id, module, body) = match def {
            DefWithBodyId::FunctionId(f) => {
                let f = f.lookup(db);
                let src = f.source(db);
                params = src.value.param_list();
                (src.file_id, f.module(db), src.value.body().map(ast::Expr::from))
            }
            DefWithBodyId::ConstId(c) => {
                let c = c.lookup(db);
                let src = c.source(db);
                (src.file_id, c.module(db), src.value.body())
            }
            DefWithBodyId::StaticId(s) => {
                let s = s.lookup(db);
                let src = s.source(db);
                (src.file_id, s.module(db), src.value.body())
            }
        };
        let expander = Expander::new(db, file_id, module);
        let (body, source_map) = Body::new(db, def, expander, params, body);
        (Arc::new(body), Arc::new(source_map))
    }

    pub(crate) fn body_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<Body> {
        db.body_with_source_map(def).0
    }

    fn new(
        db: &dyn DefDatabase,
        def: DefWithBodyId,
        expander: Expander,
        params: Option<ast::ParamList>,
        body: Option<ast::Expr>,
    ) -> (Body, BodySourceMap) {
        lower::lower(db, def, expander, params, body)
    }
}

impl Index<ExprId> for Body {
    type Output = Expr;

    fn index(&self, expr: ExprId) -> &Expr {
        &self.exprs[expr]
    }
}

impl Index<PatId> for Body {
    type Output = Pat;

    fn index(&self, pat: PatId) -> &Pat {
        &self.pats[pat]
    }
}

impl BodySourceMap {
    pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> {
        self.expr_map_back[expr].clone()
    }

    pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprId> {
        let src = node.map(|it| AstPtr::new(it));
        self.expr_map.get(&src).cloned()
    }

    pub fn node_macro_file(&self, node: InFile<&ast::MacroCall>) -> Option<HirFileId> {
        let src = node.map(|it| AstPtr::new(it));
        self.expansions.get(&src).cloned()
    }

    pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> {
        self.pat_map_back[pat].clone()
    }

    pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<PatId> {
        let src = node.map(|it| Either::Left(AstPtr::new(it)));
        self.pat_map.get(&src).cloned()
    }

    pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordField>> {
        self.field_map[&(expr, field)].clone()
    }
}
<|endoftext|>


<commit_before>#[allow(unused_imports)]
pub mod backend;
pub mod thnn;

pub use self::backend::*;
pub use self::thnn::*;
<commit_msg>switch to auto-generated code<commit_after>#[allow(unused_imports)]
pub mod backend;
pub mod thnn_float;
pub mod thnn_double;

pub use self::backend::*;
pub use self::thnn_float::*;
pub use self::thnn_double::*;
<|endoftext|>


<commit_before>/// Ye Olde Await Macro
///
/// Basically a translation of polling to yielding. This crate's macro is
/// reexported in the `futures_await` crate, you should not use this crate
/// specifically. If I knew how to define this macro in the `futures_await`
/// crate I would. Ideally this crate would not exist.

// TODO: how to define this in the `futures_await` crate but have it still
// importable via `futurses_await::prelude::await`?

#[macro_export]
macro_rules! await {
    ($e:expr) => ({
        let mut future = $e;
        loop {
            match ::futures::Future::poll(&mut future) {
                ::futures::__rt::Ok(::futures::Async::Ready(e)) => {
                    break ::futures::__rt::Ok(e)
                }
                ::futures::__rt::Ok(::futures::Async::NotReady) => {}
                ::futures::__rt::Err(e) => {
                    break ::futures::__rt::Err(e)
                }
            }
            yield ::futures::Async::NotReady
        }
    })
}

#[macro_export]
macro_rules! stream_yield {
    ($e:expr) => ({
        let e = $e;
        yield ::futures::Async::Ready(e)
    })
}
<commit_msg>Add comment on why stream_yield uses a temporary<commit_after>/// Ye Olde Await Macro
///
/// Basically a translation of polling to yielding. This crate's macro is
/// reexported in the `futures_await` crate, you should not use this crate
/// specifically. If I knew how to define this macro in the `futures_await`
/// crate I would. Ideally this crate would not exist.

// TODO: how to define this in the `futures_await` crate but have it still
// importable via `futurses_await::prelude::await`?

#[macro_export]
macro_rules! await {
    ($e:expr) => ({
        let mut future = $e;
        loop {
            match ::futures::Future::poll(&mut future) {
                ::futures::__rt::Ok(::futures::Async::Ready(e)) => {
                    break ::futures::__rt::Ok(e)
                }
                ::futures::__rt::Ok(::futures::Async::NotReady) => {}
                ::futures::__rt::Err(e) => {
                    break ::futures::__rt::Err(e)
                }
            }
            yield ::futures::Async::NotReady
        }
    })
}

// TODO: This macro needs to use an extra temporary variable because of
// rust-lang/rust#44197, once that's fixed this should just use $e directly
// inside the yield expression
#[macro_export]
macro_rules! stream_yield {
    ($e:expr) => ({
        let e = $e;
        yield ::futures::Async::Ready(e)
    })
}
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Benoit Benedetti <benoit.benedetti@gmail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

/* last synced with: logname (GNU coreutils) 8.22 */

// spell-checker:ignore (ToDO) getlogin userlogin

#[macro_use]
extern crate uucore;

use std::ffi::CStr;
use uucore::InvalidEncodingHandling;

use clap::App;

extern "C" {
    // POSIX requires using getlogin (or equivalent code)
    pub fn getlogin() -> *const libc::c_char;
}

fn get_userlogin() -> Option<String> {
    unsafe {
        let login: *const libc::c_char = getlogin();
        if login.is_null() {
            None
        } else {
            Some(String::from_utf8_lossy(CStr::from_ptr(login).to_bytes()).to_string())
        }
    }
}

static SUMMARY: &str = "Print user's login name";
static VERSION: &str = env!("CARGO_PKG_VERSION");

fn get_usage() -> String {
    format!("{0}", executable!())
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let _ = args
        .collect_str(InvalidEncodingHandling::Ignore)
        .accept_any();

    let usage = get_usage();

    let _ = App::new(executable!())
        .version(VERSION)
        .about(SUMMARY)
        .usage(&usage[..])
        .get_matches();

    match get_userlogin() {
        Some(userlogin) => println!("{}", userlogin),
        None => show_error!("no login name"),
    }

    0
}
<commit_msg>logname: fix test & style warning<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Benoit Benedetti <benoit.benedetti@gmail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

/* last synced with: logname (GNU coreutils) 8.22 */

// spell-checker:ignore (ToDO) getlogin userlogin

#[macro_use]
extern crate uucore;

use std::ffi::CStr;
use uucore::InvalidEncodingHandling;

use clap::App;

extern "C" {
    // POSIX requires using getlogin (or equivalent code)
    pub fn getlogin() -> *const libc::c_char;
}

fn get_userlogin() -> Option<String> {
    unsafe {
        let login: *const libc::c_char = getlogin();
        if login.is_null() {
            None
        } else {
            Some(String::from_utf8_lossy(CStr::from_ptr(login).to_bytes()).to_string())
        }
    }
}

static SUMMARY: &str = "Print user's login name";
static VERSION: &str = env!("CARGO_PKG_VERSION");

fn get_usage() -> String {
    String::from(executable!())
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let args = args
        .collect_str(InvalidEncodingHandling::Ignore)
        .accept_any();

    let usage = get_usage();
    let _ = App::new(executable!())
        .version(VERSION)
        .about(SUMMARY)
        .usage(&usage[..])
        .get_matches_from(args);

    match get_userlogin() {
        Some(userlogin) => println!("{}", userlogin),
        None => show_error!("no login name"),
    }

    0
}
<|endoftext|>


<commit_before>extern crate errno;

extern crate libc;

use super::constants::*;
use super::ffi::*;

use std::ffi::CString;
use std::os::unix::raw::{gid_t, uid_t};
use std::ptr;
use std::result;
use std::str;

pub type Error = errno::Errno;
pub type Result<T> = result::Result<T, Error>;

fn check_call<T>(res: libc::c_long, value: T) -> Result<T> {
    match res {
        0   => Ok(value),
        -1  => Err(errno::errno()),
        _   => unreachable!(),
    }
}

fn get_keyring_id(id: KeyringSerial, create: bool) -> Result<KeyringSerial> {
    let res = unsafe { keyctl_get_keyring_ID(id, create as libc::c_int) };
    check_call(res as libc::c_long, res)
}

pub struct Keyring {
    id: KeyringSerial,
}

impl Keyring {
    pub fn set_default(keyring: DefaultKeyring) -> Result<()> {
        check_call(unsafe { keyctl_set_reqkey_keyring(keyring.serial()) }, ())
    }

    pub fn export_session_keyring_to_parent() -> Result<()> {
        check_call(unsafe { keyctl_session_to_parent() }, ())
    }

    pub fn attach(id: KeyringSerial) -> Result<Self> {
        get_keyring_id(id, false)
            .map(|id| {
                Keyring {
                    id: id,
                }
            })
    }

    pub fn attach_or_create(id: KeyringSerial) -> Result<Self> {
        get_keyring_id(id, true)
            .map(|id| {
                Keyring {
                    id: id,
                }
            })
    }

    pub fn join_session(name: Option<&str>) -> Result<Self> {
        let nameptr = if let Some(namestr) = name {
                CString::new(namestr).unwrap().as_ptr()
            } else {
                ptr::null()
            };
        let res = unsafe { keyctl_join_session_keyring(nameptr) };
        check_call(res as libc::c_long, res)
            .map(|id| {
                Keyring {
                    id: id,
                }
            })
    }

    pub fn clear(&mut self) -> Result<()> {
        check_call(unsafe { keyctl_clear(self.id) }, ())
    }

    pub fn link(&mut self, key: &Key) -> Result<()> {
        check_call(unsafe { keyctl_link(key.id, self.id) }, ())
    }

    pub fn unlink(&mut self, key: &Key) -> Result<()> {
        check_call(unsafe { keyctl_unlink(key.id, self.id) }, ())
    }

    pub fn search(&self, type_: &str, description: &str, dest: Option<Keyring>) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let destid = if let Some(dest_ring) = dest {
                dest_ring.id
            } else {
                0
            };
        let res = unsafe { keyctl_search(self.id, typeptr, descptr, destid) };
        check_call(res, Key { id: res as key_serial_t, })
    }

    pub fn read(&self) -> Result<Vec<Key>> {
        unimplemented!()
    }

    pub fn attach_persistent(&mut self) -> Result<Keyring> {
        let res = unsafe { keyctl_get_persistent(-1, self.id) };
        check_call(res, Keyring { id: res as key_serial_t, })
    }

    pub fn add_key(&mut self, description: &str, payload: &[u8]) -> Result<Key> {
        let typeptr = CString::new("user").unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { add_key(typeptr, descptr, payload.as_ptr() as *const libc::c_void, payload.len(), self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn add_keyring(&mut self) -> Result<Keyring> {
        let typeptr = CString::new("keyring").unwrap().as_ptr();
        let res = unsafe { add_key(typeptr, ptr::null(), ptr::null(), 0, self.id) };
        check_call(res as libc::c_long, Keyring { id: res, })
    }

    pub fn request_key(&mut self) -> Result<Key> {
        unimplemented!()
    }
}

pub struct Key {
    id: KeyringSerial,
}

impl Key {
    pub fn keyring(&self) -> Result<Keyring> {
        get_keyring_id(self.id, false)
            .map(|id| {
                Keyring {
                    id: id,
                }
            })
    }

    pub fn update(&mut self, data: &[u8]) -> Result<()> {
        check_call(unsafe { keyctl_update(self.id, data.as_ptr() as *const libc::c_void, data.len()) }, ())
    }

    pub fn revoke(self) -> Result<()> {
        check_call(unsafe { keyctl_revoke(self.id) }, ())
    }

    pub fn chown(&mut self, uid: uid_t, gid: gid_t) -> Result<()> {
        check_call(unsafe { keyctl_chown(self.id, uid, gid) }, ())
    }

    pub fn set_permissions(&mut self, perms: KeyPermissions) -> Result<()> {
        check_call(unsafe { keyctl_setperm(self.id, perms) }, ())
    }

    pub fn description(&self) -> Result<String> {
        let sz = unsafe { keyctl_describe(self.id, ptr::null_mut(), 0) };
        if sz < 0 {
            return Err(errno::errno());
        }
        let mut buffer = Vec::with_capacity(sz as usize);
        let res = unsafe { keyctl_describe(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) };
        if res < 0 {
            return Err(errno::errno());
        }
        let str_slice = str::from_utf8(&buffer[..]).unwrap();
        Ok(str_slice.to_owned())
    }

    pub fn read(&self) -> Result<Vec<u8>> {
        let sz = unsafe { keyctl_read(self.id, ptr::null_mut(), 0) };
        if sz < 0 {
            return Err(errno::errno());
        }
        let mut buffer = Vec::with_capacity(sz as usize);
        let res = unsafe { keyctl_read(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) };
        if res < 0 {
            return Err(errno::errno());
        }
        Ok(buffer)
    }

    pub fn set_timeout(&mut self, timeout: u32) -> Result<()> {
        check_call(unsafe { keyctl_set_timeout(self.id, timeout) }, ())
    }

    pub fn get_security(&self) -> Result<String> {
        let sz = unsafe { keyctl_get_security(self.id, ptr::null_mut(), 0) };
        if sz < 0 {
            return Err(errno::errno());
        }
        let mut buffer = Vec::with_capacity(sz as usize);
        let res = unsafe { keyctl_get_security(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) };
        if res < 0 {
            return Err(errno::errno());
        }
        let str_slice = str::from_utf8(&buffer[..]).unwrap();
        Ok(str_slice.to_owned())
    }

    pub fn invalidate(self) -> Result<()> {
        check_call(unsafe { keyctl_invalidate(self.id) }, ())
    }
}
<commit_msg>api: some functions return meaningful values<commit_after>extern crate errno;

extern crate libc;

use super::constants::*;
use super::ffi::*;

use std::ffi::CString;
use std::os::unix::raw::{gid_t, uid_t};
use std::ptr;
use std::result;
use std::str;

pub type Error = errno::Errno;
pub type Result<T> = result::Result<T, Error>;

fn check_call<T>(res: libc::c_long, value: T) -> Result<T> {
    if res == -1 {
        Err(errno::errno())
    } else {
        Ok(value)
    }
}

fn get_keyring_id(id: KeyringSerial, create: bool) -> Result<KeyringSerial> {
    let res = unsafe { keyctl_get_keyring_ID(id, create as libc::c_int) };
    check_call(res as libc::c_long, res)
}

pub struct Keyring {
    id: KeyringSerial,
}

impl Keyring {
    pub fn set_default(keyring: DefaultKeyring) -> Result<()> {
        check_call(unsafe { keyctl_set_reqkey_keyring(keyring.serial()) }, ())
    }

    pub fn export_session_keyring_to_parent() -> Result<()> {
        check_call(unsafe { keyctl_session_to_parent() }, ())
    }

    pub fn attach(id: KeyringSerial) -> Result<Self> {
        get_keyring_id(id, false)
            .map(|id| {
                Keyring {
                    id: id,
                }
            })
    }

    pub fn attach_or_create(id: KeyringSerial) -> Result<Self> {
        get_keyring_id(id, true)
            .map(|id| {
                Keyring {
                    id: id,
                }
            })
    }

    pub fn join_session(name: Option<&str>) -> Result<Self> {
        let nameptr = if let Some(namestr) = name {
                CString::new(namestr).unwrap().as_ptr()
            } else {
                ptr::null()
            };
        let res = unsafe { keyctl_join_session_keyring(nameptr) };
        check_call(res as libc::c_long, res)
            .map(|id| {
                Keyring {
                    id: id,
                }
            })
    }

    pub fn clear(&mut self) -> Result<()> {
        check_call(unsafe { keyctl_clear(self.id) }, ())
    }

    pub fn link(&mut self, key: &Key) -> Result<()> {
        check_call(unsafe { keyctl_link(key.id, self.id) }, ())
    }

    pub fn unlink(&mut self, key: &Key) -> Result<()> {
        check_call(unsafe { keyctl_unlink(key.id, self.id) }, ())
    }

    pub fn search(&self, type_: &str, description: &str, dest: Option<Keyring>) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let destid = if let Some(dest_ring) = dest {
                dest_ring.id
            } else {
                0
            };
        let res = unsafe { keyctl_search(self.id, typeptr, descptr, destid) };
        check_call(res, Key { id: res as key_serial_t, })
    }

    pub fn read(&self) -> Result<Vec<Key>> {
        unimplemented!()
    }

    pub fn attach_persistent(&mut self) -> Result<Keyring> {
        let res = unsafe { keyctl_get_persistent(-1, self.id) };
        check_call(res, Keyring { id: res as key_serial_t, })
    }

    pub fn add_key(&mut self, description: &str, payload: &[u8]) -> Result<Key> {
        let typeptr = CString::new("user").unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { add_key(typeptr, descptr, payload.as_ptr() as *const libc::c_void, payload.len(), self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn add_keyring(&mut self) -> Result<Keyring> {
        let typeptr = CString::new("keyring").unwrap().as_ptr();
        let res = unsafe { add_key(typeptr, ptr::null(), ptr::null(), 0, self.id) };
        check_call(res as libc::c_long, Keyring { id: res, })
    }

    pub fn request_key(&mut self) -> Result<Key> {
        unimplemented!()
    }
}

pub struct Key {
    id: KeyringSerial,
}

impl Key {
    pub fn keyring(&self) -> Result<Keyring> {
        get_keyring_id(self.id, false)
            .map(|id| {
                Keyring {
                    id: id,
                }
            })
    }

    pub fn update(&mut self, data: &[u8]) -> Result<()> {
        check_call(unsafe { keyctl_update(self.id, data.as_ptr() as *const libc::c_void, data.len()) }, ())
    }

    pub fn revoke(self) -> Result<()> {
        check_call(unsafe { keyctl_revoke(self.id) }, ())
    }

    pub fn chown(&mut self, uid: uid_t, gid: gid_t) -> Result<()> {
        check_call(unsafe { keyctl_chown(self.id, uid, gid) }, ())
    }

    pub fn set_permissions(&mut self, perms: KeyPermissions) -> Result<()> {
        check_call(unsafe { keyctl_setperm(self.id, perms) }, ())
    }

    pub fn description(&self) -> Result<String> {
        let sz = unsafe { keyctl_describe(self.id, ptr::null_mut(), 0) };
        if sz < 0 {
            return Err(errno::errno());
        }
        let mut buffer = Vec::with_capacity(sz as usize);
        let res = unsafe { keyctl_describe(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) };
        if res < 0 {
            return Err(errno::errno());
        }
        let str_slice = str::from_utf8(&buffer[..]).unwrap();
        Ok(str_slice.to_owned())
    }

    pub fn read(&self) -> Result<Vec<u8>> {
        let sz = unsafe { keyctl_read(self.id, ptr::null_mut(), 0) };
        if sz < 0 {
            return Err(errno::errno());
        }
        let mut buffer = Vec::with_capacity(sz as usize);
        let res = unsafe { keyctl_read(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) };
        if res < 0 {
            return Err(errno::errno());
        }
        Ok(buffer)
    }

    pub fn set_timeout(&mut self, timeout: u32) -> Result<()> {
        check_call(unsafe { keyctl_set_timeout(self.id, timeout) }, ())
    }

    pub fn get_security(&self) -> Result<String> {
        let sz = unsafe { keyctl_get_security(self.id, ptr::null_mut(), 0) };
        if sz < 0 {
            return Err(errno::errno());
        }
        let mut buffer = Vec::with_capacity(sz as usize);
        let res = unsafe { keyctl_get_security(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) };
        if res < 0 {
            return Err(errno::errno());
        }
        let str_slice = str::from_utf8(&buffer[..]).unwrap();
        Ok(str_slice.to_owned())
    }

    pub fn invalidate(self) -> Result<()> {
        check_call(unsafe { keyctl_invalidate(self.id) }, ())
    }
}
<|endoftext|>


<commit_before>use std::thread;
use std::sync::Arc;
use std::sync::mpsc::channel;
use std::sync::mpsc::Sender;
use std::path::Path;
use std::net::SocketAddr;
use std::error::Error;
use std::fs::File;

use hyper::Server;
use hyper::server::Handler;
use hyper::server::Request;
use hyper::server::Response;
use hyper::net::HttpsListener;
use hyper::net::NetworkListener;
use hyper::net::Openssl;
use hyper::header::ContentType;
use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};

use openssl::ssl::{SslContext, SSL_OP_NO_TLSV1, SSL_OP_NO_TLSV1_1, SslMethod, SSL_VERIFY_PEER, SSL_VERIFY_FAIL_IF_NO_PEER_CERT};
use openssl::x509::X509;
use openssl::x509::X509FileType;
use openssl::x509::X509StoreContext;
use openssl::ssl::error::SslError;
use openssl::nid::Nid;

use std::collections::BTreeMap;

use mio::Sender as MioSender;

use rustc_serialize::json;

//const CIPHERS: &'static str = "DEFAULT";
const CIPHERS: &'static str = "AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:CAMELLIA256-SHA";

pub type SniMap = BTreeMap<String, String>;

pub enum ApiMsg {
    SniRequest(Sender<ApiMsg>),
    SniResponse(SniMap),
}

#[derive(RustcEncodable)]
pub struct ExampleResponse {
    map: SniMap,
}

#[derive(Debug)]
pub struct Api {
    key_path: String,
    cert_path: String,
    client_cert_path: String,
    main_channel: MioSender<ApiMsg>,
}

impl Api {
    pub fn new(key: &str, cert: &str, client_cert: &str, main_channel: MioSender<ApiMsg>) -> Api {
        Api {
            key_path: key.to_string(),
            cert_path: cert.to_string(),
            client_cert_path: client_cert.to_string(),
            main_channel: main_channel,
        }
    }

    pub fn spawn(self) -> SocketAddr {
        //let api = Api::new("api_key.pem", "api_cert.pem", "client_cert.pem");
        info!("Starting api endpoint: {:?}", self);
        //Openssl::with_cert_and_key
        let ssl = ctx(&self.cert_path, &self.key_path, path2pem(&self.client_cert_path))
        		.ok().expect("Could not initialize SSL context");
        let mut listener = HttpsListener::new("127.0.0.1:0", ssl)
                .expect("Could not initialize API listener");
        let local_addr = {
            let l2_ref = &mut listener;
            l2_ref.local_addr().expect("Could not determine API listener port")
        };
        let server = Server::new(listener);
        info!("API listeneing on {:?}", local_addr);

        thread::spawn(move || {
            server.handle_threads(self, 1).unwrap();
        });

        local_addr
    }
}

impl Handler for Api {
    fn handle(&self, _: Request, mut res: Response) {
        let (tx, rx) = channel();
        let send_result = self.main_channel.send(ApiMsg::SniRequest(tx));
        if send_result.is_err() {
            println!("Error talking to main event_loop");
            res.send(b"Error talking to main event_loop").unwrap();
        } else {
            let response: ApiMsg = rx.recv().unwrap();
            let sni_map = match response {
                ApiMsg::SniResponse(rex) => rex,
                _ => BTreeMap::new(),
            };

			let object = ExampleResponse {
			    map: sni_map,
			};

            let encoded = json::encode(&object).unwrap();

            res.headers_mut().set(ContentType(Mime(
                    TopLevel::Application,
                    SubLevel::Json,
                    vec![(Attr::Charset, Value::Utf8)])));

            res.send(encoded.as_bytes()).unwrap();
        }
    }
}

fn ctx<C, K>(cert: C, key: K, client_cert: Vec<u8>) -> Result<Openssl, SslError>
        where C: AsRef<Path>, K: AsRef<Path> {

    let mut ctx = try!(SslContext::new(SslMethod::Sslv23));
    let opts = ctx.get_options();
    ctx.set_options(opts | SSL_OP_NO_TLSV1 | SSL_OP_NO_TLSV1_1);
    try!(ctx.set_cipher_list(CIPHERS));
    try!(ctx.set_certificate_file(cert.as_ref(), X509FileType::PEM));
    try!(ctx.set_private_key_file(key.as_ref(), X509FileType::PEM));
    ctx.set_verify_with_data(
        SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
        verifier,
        client_cert);
    Ok(Openssl { context: Arc::new(ctx) })
}

fn verifier(_preverify_ok: bool, x509_ctx: &X509StoreContext, client_cert: &Vec<u8>) -> bool {
    match x509_ctx.get_current_cert() {
    	None => {
    	    warn!("Rejecting client cert because X509StoreContext::get_current_cert() failed!");
    	    false
    	},
    	Some(cert) => {
    	    debug!("Client cert subject: {:?}", cert.subject_name().text_by_nid(Nid::CN));
    	    let mut buf = Vec::new();
    	    if cert.write_pem(&mut buf).is_err() {
    	        warn!("Rejecting client because peer cert could not be obtained");
    	        false
    	    } else {
    	        if buf == *client_cert {
    	            true
    	        } else {
                    warn!("Rejecting client cert {:?}", String::from_utf8(buf.clone()));
                    false
    	        }
    	    }
    	}
    }
}

fn path2pem(path1: &str) -> Vec<u8> {
    let path = Path::new(path1);

    let mut file = match File::open(&path) {
        // The `description` method of `io::Error` returns a string that
        // describes the error
        Err(why) => {
            let display = path.display();
            panic!("couldn't open {}: {}", display, Error::description(&why))
        },
        Ok(file) => file,
    };

    let cert = X509::from_pem(&mut file).expect("Unable to parse PEM"); //format!("Failed to parse pem {:?}", path1)
	let mut buf = Vec::new();
    cert.write_pem(&mut buf).expect("Unable to serialize PEM");

    buf
}
<commit_msg>API cleanups: request path is now handled correctly.<commit_after>use std::thread;
use std::sync::Arc;
use std::sync::mpsc::channel;
use std::sync::mpsc::Sender;
use std::path::Path;
use std::net::SocketAddr;
use std::error::Error;
use std::fs::File;

use hyper::Server;
use hyper::server::Handler;
use hyper::server::Request;
use hyper::server::Response;
use hyper::status::StatusCode;
use hyper::net::HttpsListener;
use hyper::net::NetworkListener;
use hyper::net::Openssl;
use hyper::header::ContentType;
use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
use hyper::uri::RequestUri;

use openssl::ssl::{SslContext, SSL_OP_NO_TLSV1, SSL_OP_NO_TLSV1_1, SslMethod, SSL_VERIFY_PEER, SSL_VERIFY_FAIL_IF_NO_PEER_CERT};
use openssl::x509::X509;
use openssl::x509::X509FileType;
use openssl::x509::X509StoreContext;
use openssl::ssl::error::SslError;
use openssl::nid::Nid;

use std::collections::BTreeMap;

use mio::Sender as MioSender;

use rustc_serialize::json;

//const CIPHERS: &'static str = "DEFAULT";
const CIPHERS: &'static str = "AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:CAMELLIA256-SHA";

pub type SniMap = BTreeMap<String, String>;

pub enum ApiMsg {
    SniRequest(Sender<ApiMsg>),
    SniResponse(SniMap),
}

#[derive(RustcEncodable)]
pub struct ExampleResponse {
    map: SniMap,
}

#[derive(Debug)]
pub struct Api {
    key_path: String,
    cert_path: String,
    client_cert_path: String,
    main_channel: MioSender<ApiMsg>,
}

impl Api {
    pub fn new(key: &str, cert: &str, client_cert: &str, main_channel: MioSender<ApiMsg>) -> Api {
        Api {
            key_path: key.to_string(),
            cert_path: cert.to_string(),
            client_cert_path: client_cert.to_string(),
            main_channel: main_channel,
        }
    }

    pub fn spawn(self) -> SocketAddr {
        //let api = Api::new("api_key.pem", "api_cert.pem", "client_cert.pem");
        info!("Starting api endpoint: {:?}", self);
        //Openssl::with_cert_and_key
        let ssl = ctx(&self.cert_path, &self.key_path, path2pem(&self.client_cert_path))
        		.ok().expect("Could not initialize SSL context");
        let mut listener = HttpsListener::new("127.0.0.1:0", ssl)
                .expect("Could not initialize API listener");
        let local_addr = {
            let l2_ref = &mut listener;
            l2_ref.local_addr().expect("Could not determine API listener port")
        };
        let server = Server::new(listener);
        info!("API listeneing on {:?}", local_addr);

        thread::spawn(move || {
            server.handle_threads(self, 1).unwrap();
        });

        local_addr
    }
}

fn respond(mut res: Response, code: StatusCode, body: &[u8]) {
    *res.status_mut() = code;
    res.send(body).ok().expect("Could not send response!");
}

impl Handler for Api {
    fn handle(&self, req: Request, mut res: Response) {
        match req.uri {
            RequestUri::AbsolutePath(path) => {
                info!("{}", path);
                let (tx, rx) = channel();
                if path == "/" {
                    let send_result = self.main_channel.send(ApiMsg::SniRequest(tx));
                    if send_result.is_err() {
                        println!("Error talking to main event_loop");
                        respond(res, StatusCode::InternalServerError, b"Error talking to main event_loop");
                    } else {
                        let response: ApiMsg = rx.recv().unwrap();
                        let sni_map = match response {
                            ApiMsg::SniResponse(rex) => rex,
                            _ => BTreeMap::new(),
                        };

            			let object = ExampleResponse {
            			    map: sni_map,
            			};

                        let encoded = json::encode(&object).unwrap();

                        res.headers_mut().set(ContentType(Mime(
                                TopLevel::Application,
                                SubLevel::Json,
                                vec![(Attr::Charset, Value::Utf8)])));

                        respond(res, StatusCode::Ok, encoded.as_bytes());
                    }
                } else if path == "/about" {
                    respond(res, StatusCode::Ok, b"TODO: Implement me!");
                } else {
                    respond(res, StatusCode::NotFound, format!("Resource not found on server: {}", path).as_bytes());
                }
            },
            _ => {
                respond(res, StatusCode::BadRequest, b"Bad request");
            }
        }
    }
}

fn ctx<C, K>(cert: C, key: K, client_cert: Vec<u8>) -> Result<Openssl, SslError>
        where C: AsRef<Path>, K: AsRef<Path> {

    let mut ctx = try!(SslContext::new(SslMethod::Sslv23));
    let opts = ctx.get_options();
    ctx.set_options(opts | SSL_OP_NO_TLSV1 | SSL_OP_NO_TLSV1_1);
    try!(ctx.set_cipher_list(CIPHERS));
    try!(ctx.set_certificate_file(cert.as_ref(), X509FileType::PEM));
    try!(ctx.set_private_key_file(key.as_ref(), X509FileType::PEM));
    ctx.set_verify_with_data(
        SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
        verifier,
        client_cert);
    Ok(Openssl { context: Arc::new(ctx) })
}

fn verifier(_preverify_ok: bool, x509_ctx: &X509StoreContext, client_cert: &Vec<u8>) -> bool {
    match x509_ctx.get_current_cert() {
    	None => {
    	    warn!("Rejecting client cert because X509StoreContext::get_current_cert() failed!");
    	    false
    	},
    	Some(cert) => {
    	    debug!("Client cert subject: {:?}", cert.subject_name().text_by_nid(Nid::CN));
    	    let mut buf = Vec::new();
    	    if cert.write_pem(&mut buf).is_err() {
    	        warn!("Rejecting client because peer cert could not be obtained");
    	        false
    	    } else {
    	        if buf == *client_cert {
    	            true
    	        } else {
                    warn!("Rejecting client cert {:?}", String::from_utf8(buf.clone()));
                    false
    	        }
    	    }
    	}
    }
}

fn path2pem(path1: &str) -> Vec<u8> {
    let path = Path::new(path1);

    let mut file = match File::open(&path) {
        // The `description` method of `io::Error` returns a string that
        // describes the error
        Err(why) => {
            let display = path.display();
            panic!("couldn't open {}: {}", display, Error::description(&why))
        },
        Ok(file) => file,
    };

    let cert = X509::from_pem(&mut file).expect("Unable to parse PEM"); //format!("Failed to parse pem {:?}", path1)
	let mut buf = Vec::new();
    cert.write_pem(&mut buf).expect("Unable to serialize PEM");

    buf
}
<|endoftext|>