<commit_before>use serde_json;
use std::collections::{HashSet, HashMap};
use std::f64::consts::PI;
use std::fmt;

const PRECISION: f64 = 10000.0;

/// Point containing latitude and longitude values as integers.
/// Integers are used here due to Rust itself not providing some basic
/// floating point functionality at the moment. All due to the undefined
/// behavior revolving around `NaN` float values. For example, what is the boolean
/// result of `0.0 > NaN` ? Its undefined, so therefore > is not implemented by
/// Rust Proper! Perhaps they'll fix this massive inconvienence in the future.
/// TODO use floats
#[derive(PartialEq, Eq, Clone, Debug, Hash, Copy)]
pub struct Point {
    lat: i64,
    lon: i64,
}

/// Degress to Radians
fn deg2rad(deg : f64) -> f64 {
    ((2.0 * PI)/180.0) * deg
}

impl fmt::Display for Point {
    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {})", self.lat(), self.lon())
    }
}

impl Point {
    /// New integer stored Point from floating point lat/lon coordinates
    pub fn new(lat : f64, lon : f64) -> Point {
        Point {
            lat: (lat*PRECISION).floor() as i64,
            lon: (lon*PRECISION).floor() as i64,
        }
    }

    /// Latitude value
    pub fn lat(&self) -> f64 {
        (self.lat as f64)/PRECISION
    }

    /// Longitude value
    pub fn lon(&self) -> f64 {
        (self.lon as f64)/PRECISION
    }

    /// Spheroid distance calculation given earth coordinates as lat/lon values.
    /// Returns the distance in meters.
    pub fn geo_distance(&self, p : &Point) -> f64 {
        let r = 6371000.0; // metres
        let lat1 = p.lat();
        let lon1 = p.lon();
        let lat2 = self.lat();
        let lon2 = self.lon();
        let sig1 = deg2rad(lat1);
        let sig2 = deg2rad(lat2);
        let deltasig = deg2rad(lat2-lat1);
        let deltalambda = deg2rad(lon2-lon1);
        let a = (deltasig/2.0).sin() * (deltasig/2.0).sin() +
            sig1.cos() * sig2.cos() *
            (deltalambda/2.0).sin() * (deltalambda/2.0).sin();
        let c = 2.0 * a.sqrt().atan2((1.0-a).sqrt());
        r * c
    }

}

/// Path
pub type Path = Vec<Point>;

/// Maintains a sparse routing graph
pub struct RouteGraph {
    vertices: HashSet<Point>,
    edges: HashMap<Point, Vec<Point>>,
    paths: HashMap<(Point, Point), Path>,
}

/// Convert the TFL lineStrings attribute to a simple flat vectory of paths.
/// lineStrings in TFL data is a JSON array of string values, containing
/// either an array of points or an array of arrays of points, we handle both.
pub fn linestrings_to_paths(line_strings : &Vec<String>) -> Vec<Path> {
    let mut paths : Vec<Path> = Vec::new();
    for line_string in line_strings {
        match serde_json::from_str::<Vec<(f64, f64)>>(&line_string) {
            Ok(raw_path) => paths.push(raw_path.iter().map(|&(lon, lat)| Point::new(lat, lon)).collect()),
            Err(err) => {
                match serde_json::from_str::<Vec<Vec<(f64, f64)>>>(&line_string) {
                    Ok(raw_paths) => {
                        for raw_path in raw_paths {
                            paths.push(raw_path.iter().map(|&(lon, lat)| Point::new(lat, lon)).collect());
                        }
                    },
                    Err(err2) => println!("Errors decoding line string, single line {}, multi line {}", err, err2),
                }
            },
        }
    }
    paths
}

impl RouteGraph {
    /// New Route Graph
    pub fn new() -> RouteGraph {
        RouteGraph {
            vertices: HashSet::new(),
            edges: HashMap::new(),
            paths: HashMap::new(),
        }
    }

    /// Add many paths
    pub fn add_paths(&mut self, paths : &Vec<Path>) {
        for path in paths {
            self.add_path(path);
        }
    }

    /// Add single path to the graph
    pub fn add_path(&mut self, path : &Path) {
        // add points
        let first = path.first().unwrap();
        let last = path.last().unwrap();
        self.vertices.insert(first.clone());
        self.vertices.insert(last.clone());

        // add bidirectional edges
        self.edges.entry(first.clone()).or_insert(vec![last.clone()]).push(last.clone());
        self.edges.entry(last.clone()).or_insert(vec![first.clone()]).push(first.clone());

        // add paths
        self.paths.insert((first.clone(), last.clone()), path.clone());
        self.paths.insert((last.clone(), first.clone()), path.iter().rev().cloned().collect());
        assert!(self.paths.contains_key(&(first.clone(), last.clone())));
        assert!(self.paths.contains_key(&(last.clone(), first.clone())));
    }

    /// Find the closest actual point (vertex) in our graph since they are not
    /// going to be exact matches
    fn closest_point(&self, pt : &Point) -> (Point, f64) {
        let far_pt = Point::new(pt.lat()+90.0, pt.lon()+90.0);
        let far_dist = far_pt.geo_distance(pt);
        let (min_pt, min_dist) = self.edges.keys().fold((&far_pt, far_dist), |(min_pt, min_dist), vert| {
            let vert_dist = vert.geo_distance(pt);
            match vert_dist < min_dist {
                true => (vert, vert_dist),
                false => (min_pt, min_dist),
            }
        });
        (min_pt.clone(), min_dist)
    }

    /// Find a path between two points if one exists
    pub fn path(&self, p0 : Point, p1 : Point) -> Option<Path> {
        let (start, start_dist) = self.closest_point(&p0);
        if start_dist > 2000.0 {
            println!("start point {} to closest {} distance is {} > 2000", p0, start, start_dist);
            return None;
        }
        let (end, end_dist) = self.closest_point(&p1);
        if end_dist > 2000.0 {
            println!("end point {} to closest {} distance is {} > 2000", p1, end, end_dist);
            return None;
        }
        let visited : HashSet<Point> = HashSet::new();
        self.find_path(start, end, &visited)
    }

    // Recursively search the path graph from p0 to p1, when a path is found
    // the callstack will inherently build up a single Path containing all the
    // points between the two.
    // Visited is a simple HashSet marking points we've already visited to avoid
    // infinitely recursing in circles.
    fn find_path(&self, p0 : Point, p1 : Point, visited : &HashSet<Point>) -> Option<Path> {
        match self.edges.get(&p0) {
            Some(to_vertices) => {
                if visited.contains(&p0) {
                    None
                } else {
                    for next in to_vertices {
                        if next.clone() == p1 {
                            return Some(self.paths.get(&(p0, next.clone())).unwrap().clone());
                        }
                        let mut visited0 = visited.clone();
                        visited0.insert(next.clone());

                        if let Some(path) = self.find_path(next.clone(), p1, &visited0) {
                            return Some(vec![&(self.paths.get(&(p0, next.clone())).unwrap())[..], &path[..]].concat());
                        }
                    }

                    None
                }
            },
            None => None,
        }
    }
}
<commit_msg>Remove unnecessary clone()<commit_after>use serde_json;
use std::collections::{HashSet, HashMap};
use std::f64::consts::PI;
use std::fmt;

const PRECISION: f64 = 10000.0;

/// Point containing latitude and longitude values as integers.
/// Integers are used here due to Rust itself not providing some basic
/// floating point functionality at the moment. All due to the undefined
/// behavior revolving around `NaN` float values. For example, what is the boolean
/// result of `0.0 > NaN` ? Its undefined, so therefore > is not implemented by
/// Rust Proper! Perhaps they'll fix this massive inconvienence in the future.
/// TODO use floats
#[derive(PartialEq, Eq, Clone, Debug, Hash, Copy)]
pub struct Point {
    lat: i64,
    lon: i64,
}

/// Degress to Radians
fn deg2rad(deg: f64) -> f64 {
    ((2.0 * PI) / 180.0) * deg
}

impl fmt::Display for Point {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {})", self.lat(), self.lon())
    }
}

impl Point {
    /// New integer stored Point from floating point lat/lon coordinates
    pub fn new(lat: f64, lon: f64) -> Point {
        Point {
            lat: (lat * PRECISION).floor() as i64,
            lon: (lon * PRECISION).floor() as i64,
        }
    }

    /// Latitude value
    pub fn lat(&self) -> f64 {
        (self.lat as f64) / PRECISION
    }

    /// Longitude value
    pub fn lon(&self) -> f64 {
        (self.lon as f64) / PRECISION
    }

    /// Spheroid distance calculation given earth coordinates as lat/lon values.
    /// Returns the distance in meters.
    pub fn geo_distance(&self, p: &Point) -> f64 {
        let r = 6371000.0; // metres
        let lat1 = p.lat();
        let lon1 = p.lon();
        let lat2 = self.lat();
        let lon2 = self.lon();
        let sig1 = deg2rad(lat1);
        let sig2 = deg2rad(lat2);
        let deltasig = deg2rad(lat2 - lat1);
        let deltalambda = deg2rad(lon2 - lon1);
        let a = (deltasig / 2.0).sin() * (deltasig / 2.0).sin() +
            sig1.cos() * sig2.cos() *
            (deltalambda / 2.0).sin() * (deltalambda / 2.0).sin();
        let c = 2.0 * a.sqrt().atan2((1.0 - a).sqrt());
        r * c
    }

}

/// Path
pub type Path = Vec<Point>;

/// Maintains a sparse routing graph
#[derive(Default)]
pub struct RouteGraph {
    vertices: HashSet<Point>,
    edges: HashMap<Point, Vec<Point>>,
    paths: HashMap<(Point, Point), Path>,
}

/// Convert the TFL lineStrings attribute to a simple flat vectory of paths.
/// lineStrings in TFL data is a JSON array of string values, containing
/// either an array of points or an array of arrays of points, we handle both.
pub fn linestrings_to_paths(line_strings: &[String]) -> Vec<Path> {
    let mut paths : Vec<Path> = Vec::new();
    for line_string in line_strings {
        match serde_json::from_str::<Vec<(f64, f64)>>(&line_string) {
            Ok(raw_path) => paths.push(raw_path.iter().map(|&(lon, lat)| Point::new(lat, lon)).collect()),
            Err(err) => {
                match serde_json::from_str::<Vec<Vec<(f64, f64)>>>(&line_string) {
                    Ok(raw_paths) => {
                        for raw_path in raw_paths {
                            paths.push(raw_path.iter().map(|&(lon, lat)| Point::new(lat, lon)).collect());
                        }
                    },
                    Err(err2) => println!("Errors decoding line string, single line {}, multi line {}", err, err2),
                }
            },
        }
    }
    paths
}

impl RouteGraph {
    /// New Route Graph
    pub fn new() -> RouteGraph {
        RouteGraph {
            vertices: HashSet::new(),
            edges: HashMap::new(),
            paths: HashMap::new(),
        }
    }

    /// Add many paths
    pub fn add_paths(&mut self, paths: &[Path]) {
        for path in paths {
            self.add_path(path);
        }
    }

    /// Add single path to the graph
    pub fn add_path(&mut self, path: &Path) {
        // add points
        let first = path.first().unwrap();
        let last = path.last().unwrap();
        self.vertices.insert(*first);
        self.vertices.insert(*last);

        // add bidirectional edges
        self.edges.entry(*first).or_insert(vec![*last]).push(*last);
        self.edges.entry(*last).or_insert(vec![*first]).push(*first);

        // add paths
        self.paths.insert((*first, *last), path.clone());
        self.paths.insert((*last, *first), path.iter().rev().cloned().collect());
        assert!(self.paths.contains_key(&(first.clone(), last.clone())));
        assert!(self.paths.contains_key(&(last.clone(), first.clone())));
    }

    /// Find the closest actual point (vertex) in our graph since they are not
    /// going to be exact matches
    fn closest_point(&self, pt: &Point) -> (Point, f64) {
        let far_pt = Point::new(pt.lat() + 90.0, pt.lon() + 90.0);
        let far_dist = far_pt.geo_distance(pt);
        let (min_pt, min_dist) = self.edges.keys().fold((&far_pt, far_dist), |(min_pt, min_dist), vert| {
            let vert_dist = vert.geo_distance(pt);
            if vert_dist < min_dist {
                (vert, vert_dist)
            } else {
                (min_pt, min_dist)
            }
        });

        (*min_pt, min_dist)
    }

    /// Find a path between two points if one exists
    pub fn path(&self, p0: Point, p1: Point) -> Option<Path> {
        let (start, start_dist) = self.closest_point(&p0);
        if start_dist > 2000.0 {
            println!("start point {} to closest {} distance is {} > 2000", p0, start, start_dist);
            return None;
        }
        let (end, end_dist) = self.closest_point(&p1);
        if end_dist > 2000.0 {
            println!("end point {} to closest {} distance is {} > 2000", p1, end, end_dist);
            return None;
        }
        let visited: HashSet<Point> = HashSet::new();
        self.find_path(start, end, &visited)
    }

    // Recursively search the path graph from p0 to p1, when a path is found
    // the callstack will inherently build up a single Path containing all the
    // points between the two.
    // Visited is a simple HashSet marking points we've already visited to avoid
    // infinitely recursing in circles.
    fn find_path(&self, p0: Point, p1: Point, visited: &HashSet<Point>) -> Option<Path> {
        match self.edges.get(&p0) {
            Some(to_vertices) => {
                if visited.contains(&p0) {
                    None
                } else {
                    for next in to_vertices {
                        if *next == p1 {
                            return Some(self.paths.get(&(p0, *next)).unwrap().clone());
                        }

                        let mut visited0 = visited.clone();
                        visited0.insert(*next);

                        if let Some(path) = self.find_path(*next, p1, &visited0) {
                            return Some(vec![&(self.paths.get(&(p0, *next)).unwrap())[..], &path[..]].concat());
                        }
                    }

                    None
                }
            },
            None => None,
        }
    }
}
<|endoftext|>


<commit_before>use std::cmp;
use std::collections::BTreeMap;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;

mod from_str;
// mod relabel;

pub mod negra;

/// Variable or terminal symbol in an MCFG.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub enum VarT<T> {
    /// `Var(i, j)` represents the `j`th component of the `i`th successor.
    /// Indexing starts from `0`.
    Var(usize, usize),
    T(T),
}

/// Composition function in an MCFG.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub struct Composition<T> {
    pub composition: Vec<Vec<VarT<T>>>,
}

impl<T> From<Vec<Vec<VarT<T>>>> for Composition<T> {
    fn from(encapsulated_value: Vec<Vec<VarT<T>>>) -> Self {
        Composition { composition: encapsulated_value }
    }
}

/// Rule of a weighted MCFG.
#[derive(Debug, PartialOrd, Ord, Clone)]
pub struct PMCFGRule<N, T, W> {
    pub head: N,
    pub tail: Vec<N>,
    pub composition: Composition<T>,
    pub weight: W,
}

impl<N, T, W> PMCFGRule<N, T, W>
    where T: Clone,
          W: Clone,
{
    pub fn map_nonterminals<F, M>(&self, f: F) -> PMCFGRule<M, T, W>
        where F: Fn(&N) -> M,
    {
        PMCFGRule {
            head: f(&self.head),
            tail: self.tail.iter().map(f).collect(),
            composition: self.composition.clone(),
            weight: self.weight.clone()
        }
    }
}

/// A weighted MCFG.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct PMCFG<N, T, W> {
    pub _dummy: PhantomData<T>,
    pub initial: Vec<N>,
    pub rules: Vec<PMCFGRule<N, T, W>>,
}

impl<N: Hash, T: Hash, W> Hash for PMCFGRule<N, T, W> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.head.hash(state);
        self.tail.hash(state);
        self.composition.hash(state);
    }
}

impl<N: PartialEq, T: PartialEq, W> PartialEq for PMCFGRule<N, T, W> {
    fn eq(&self, other: &Self) -> bool {
        self.head == other.head && self.tail == other.tail && self.composition == other.composition
    }
}

impl<N: Eq, T: Eq, W> Eq for PMCFGRule<N, T, W> {}

impl<T: fmt::Display> fmt::Display for Composition<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buffer = "".to_string();

        let mut iter0 = self.composition.iter().peekable();
        let mut iter1;

        buffer.push_str("[");
        while let Some(proj) = iter0.next() {
            iter1 = proj.into_iter().peekable();
            buffer.push_str("[");
            while let Some(vart) = iter1.next() {
                buffer.push_str(format!("{}", vart).as_str());
                if iter1.peek().is_some() {
                    buffer.push_str(", ");
                }
            }
            buffer.push_str("]");
            if iter0.peek().is_some() {
                buffer.push_str(", ");
            }
        }
        buffer.push_str("]");

        write!(f, "{}", buffer)
    }
}

impl<T: fmt::Display> fmt::Display for VarT<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            VarT::Var(i, j) => {
                write!(f, "Var {} {}", i, j)
            },
            VarT::T(ref x) => {
                write!(f, "T \"{}\"", x)
            },
        }
    }
}

impl<N: fmt::Display, T: fmt::Display, W: fmt::Display> fmt::Display for PMCFGRule<N, T, W> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
           let mut buffer = "".to_string();

           let mut iter = self.tail.iter().peekable();

           buffer.push_str("(");
           while let Some(nt) = iter.next() {
               buffer.push_str(format!("\"{}\"", nt).as_str());
               if iter.peek().is_some() {
                   buffer.push_str(", ");
               }
           }
           buffer.push_str(")");

        write!(f, "\"{}\" → {} {}  # {}", self.head, self.composition, buffer, self.weight)
        // write!(f, "\"{}\" → {}", self.head, self.composition)
    }
}

impl<N: fmt::Display, T: fmt::Display, W: fmt::Display> fmt::Display for PMCFG<N, T, W> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buffer = "".to_string();

        let mut iter = self.initial.iter().peekable();

        buffer.push_str("initial: [");
        while let Some(nt) = iter.next() {
            buffer.push_str(format!("\"{}\"", nt).as_str());
            if iter.peek().is_some() {
                buffer.push_str(", ");
            }
        }
        buffer.push_str("]\n\n");

        for r in &self.rules {
            buffer.push_str(format!("{}\n", r).as_str());
        }

        write!(f, "{}", buffer)
    }
}

pub fn evaluate<T: Clone + fmt::Debug>(term_map: &BTreeMap<Vec<usize>, Composition<T>>) -> Composition<T> {
    evaluate_pos(term_map, vec![])
}

pub fn evaluate_pos<T: Clone + fmt::Debug>(term_map: &BTreeMap<Vec<usize>, Composition<T>>, address: Vec<usize>) -> Composition<T> {
    let unexpanded_composition = &term_map.get(&address).unwrap().composition;
    let mut expanded_nonterminals: BTreeMap<_, Vec<Vec<VarT<T>>>> = BTreeMap::new();
    let mut expanded_composition = Vec::new();

    for component in unexpanded_composition {
        let mut expanded_component = Vec::new();

        for variable in component {
            match variable {
                &VarT::Var(num_nonter, num_compon) => {
                    if !expanded_nonterminals.contains_key(&num_nonter) {
                        let mut child_address = address.clone();
                        child_address.push(num_nonter);
                        let nonter_compos = evaluate_pos(term_map, child_address).composition;
                        expanded_nonterminals.insert(num_nonter, nonter_compos);
                    }

                    let nonter_compos = expanded_nonterminals.get(&num_nonter).unwrap();

                    if let Some(compon) = nonter_compos.get(num_compon) {
                        for terminal in compon {
                            expanded_component.push(terminal.clone());
                        }
                    } else {
                        panic!("{:?}: use of {}-th component of nonterminal {} that has only {} components!",
                               unexpanded_composition, num_compon, num_nonter, nonter_compos.len());
                    }

                },
                &VarT::T(ref terminal) => {
                    expanded_component.push(VarT::T(terminal.clone()));
                },
            }
        }

        expanded_composition.push(expanded_component);
    }

    Composition::from(expanded_composition)
}

pub fn to_term<K: Clone + cmp::Ord, H: Clone, T: Clone, W>(tree_map: &BTreeMap<K, PMCFGRule<H, T, W>>) -> (BTreeMap<K, Composition<T>>, BTreeMap<K, H>) {
    let mut term_map = BTreeMap::new();
    let mut head_map = BTreeMap::new();

    for (address, rule) in tree_map {
        let &PMCFGRule { ref head, tail: _, ref composition, weight: _ } = rule;
        term_map.insert(address.clone(), composition.clone());
        head_map.insert(address.clone(), head.clone());
    }

    (term_map, head_map)
}

#[cfg(test)]
mod tests {
    use super::*;
    use self::VarT::{Var, T};

    #[test]
    fn test_evaluate() {
        let mut term_map: BTreeMap<Vec<usize>, _> = BTreeMap::new();
        term_map.insert(vec![], Composition::from(vec![
            vec![Var(0, 0), Var(1, 0), Var(0, 1), Var(1, 1)]
        ]));
        term_map.insert(vec![0], Composition::from(vec![
            vec![Var(1, 0), Var(0, 0)],
            vec![Var(2, 0), Var(0, 1)]
        ]));
        term_map.insert(vec![0, 0], Composition::from(vec![
            vec![Var(1, 0), Var(0, 0)],
            vec![Var(2, 0), Var(0, 1)]
        ]));
        term_map.insert(vec![0, 0, 0], Composition::from(vec![
            vec![],
            vec![]
        ]));
        term_map.insert(vec![0, 0, 1], Composition::from(vec![
            vec![T('a')]
        ]));
        term_map.insert(vec![0, 0, 2], Composition::from(vec![
            vec![T('c')]
        ]));
        term_map.insert(vec![0, 1], Composition::from(vec![
            vec![T('a')]
        ]));
        term_map.insert(vec![0, 2], Composition::from(vec![
            vec![T('c')]
        ]));
        term_map.insert(vec![1], Composition::from(vec![
            vec![Var(1, 0), Var(0, 0)],
            vec![Var(2, 0), Var(0, 1)]
        ]));
        term_map.insert(vec![1, 0], Composition::from(vec![
            vec![],
            vec![]
        ]));
        term_map.insert(vec![1, 1], Composition::from(vec![
            vec![T('b')]
        ]));
        term_map.insert(vec![1, 2], Composition::from(vec![
            vec![T('d')]
        ]));

        let expanded_compos = Composition::from(vec![
            vec![T('a'), T('a'), T('b'), T('c'), T('c'), T('d')]
        ]);

        assert_eq!(expanded_compos, evaluate(&term_map));
    }

    #[test]
    #[should_panic(expected =
        "[[Var(0, 0), Var(0, 1)]]: use of 1-th component of nonterminal 0 that has only 1 components!"
    )]
    fn test_evaluate_invalid_composition() {
        let mut term_map: BTreeMap<Vec<usize>, _> = BTreeMap::new();
        term_map.insert(vec![], Composition::from(vec![
            vec![Var(0, 0), Var(0, 1)]
        ]));
        term_map.insert(vec![0], Composition::from(vec![
            vec![T('a')]
        ]));

        evaluate(&term_map);
    }

    #[test]
    fn test_to_term() {
        let compos0 = Composition::from(vec![
            vec![Var(0, 0), T("a"), Var(0, 1), T("b")]
        ]);
        let compos1 = Composition::from(vec![
            vec![Var(1, 0)],
            vec![T("c")]
        ]);
        let compos2 = Composition::from(vec![
            vec![],
            vec![]
        ]);

        let mut tree_map = BTreeMap::new();
        tree_map.insert(vec![], PMCFGRule {
            head: 0,
            tail: vec![],
            composition: compos0.clone(),
            weight: 0.5
        });
        tree_map.insert(vec![0], PMCFGRule {
            head: 1,
            tail: vec![],
            composition: compos1.clone(),
            weight: 1.5
        });
        tree_map.insert(vec![0, 1], PMCFGRule {
            head: 2,
            tail: vec![],
            composition: compos2.clone(),
            weight: 2.5
        });

        let mut term_map = BTreeMap::new();
        term_map.insert(vec![], compos0);
        term_map.insert(vec![0], compos1);
        term_map.insert(vec![0, 1], compos2);

        assert_eq!(term_map, to_term(&tree_map));
    }
}
<commit_msg>src/pmcfg/mod.rs: adapted test of to_term() to changes<commit_after>use std::cmp;
use std::collections::BTreeMap;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;

mod from_str;
// mod relabel;

pub mod negra;

/// Variable or terminal symbol in an MCFG.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub enum VarT<T> {
    /// `Var(i, j)` represents the `j`th component of the `i`th successor.
    /// Indexing starts from `0`.
    Var(usize, usize),
    T(T),
}

/// Composition function in an MCFG.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub struct Composition<T> {
    pub composition: Vec<Vec<VarT<T>>>,
}

impl<T> From<Vec<Vec<VarT<T>>>> for Composition<T> {
    fn from(encapsulated_value: Vec<Vec<VarT<T>>>) -> Self {
        Composition { composition: encapsulated_value }
    }
}

/// Rule of a weighted MCFG.
#[derive(Debug, PartialOrd, Ord, Clone)]
pub struct PMCFGRule<N, T, W> {
    pub head: N,
    pub tail: Vec<N>,
    pub composition: Composition<T>,
    pub weight: W,
}

impl<N, T, W> PMCFGRule<N, T, W>
    where T: Clone,
          W: Clone,
{
    pub fn map_nonterminals<F, M>(&self, f: F) -> PMCFGRule<M, T, W>
        where F: Fn(&N) -> M,
    {
        PMCFGRule {
            head: f(&self.head),
            tail: self.tail.iter().map(f).collect(),
            composition: self.composition.clone(),
            weight: self.weight.clone()
        }
    }
}

/// A weighted MCFG.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct PMCFG<N, T, W> {
    pub _dummy: PhantomData<T>,
    pub initial: Vec<N>,
    pub rules: Vec<PMCFGRule<N, T, W>>,
}

impl<N: Hash, T: Hash, W> Hash for PMCFGRule<N, T, W> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.head.hash(state);
        self.tail.hash(state);
        self.composition.hash(state);
    }
}

impl<N: PartialEq, T: PartialEq, W> PartialEq for PMCFGRule<N, T, W> {
    fn eq(&self, other: &Self) -> bool {
        self.head == other.head && self.tail == other.tail && self.composition == other.composition
    }
}

impl<N: Eq, T: Eq, W> Eq for PMCFGRule<N, T, W> {}

impl<T: fmt::Display> fmt::Display for Composition<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buffer = "".to_string();

        let mut iter0 = self.composition.iter().peekable();
        let mut iter1;

        buffer.push_str("[");
        while let Some(proj) = iter0.next() {
            iter1 = proj.into_iter().peekable();
            buffer.push_str("[");
            while let Some(vart) = iter1.next() {
                buffer.push_str(format!("{}", vart).as_str());
                if iter1.peek().is_some() {
                    buffer.push_str(", ");
                }
            }
            buffer.push_str("]");
            if iter0.peek().is_some() {
                buffer.push_str(", ");
            }
        }
        buffer.push_str("]");

        write!(f, "{}", buffer)
    }
}

impl<T: fmt::Display> fmt::Display for VarT<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            VarT::Var(i, j) => {
                write!(f, "Var {} {}", i, j)
            },
            VarT::T(ref x) => {
                write!(f, "T \"{}\"", x)
            },
        }
    }
}

impl<N: fmt::Display, T: fmt::Display, W: fmt::Display> fmt::Display for PMCFGRule<N, T, W> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
           let mut buffer = "".to_string();

           let mut iter = self.tail.iter().peekable();

           buffer.push_str("(");
           while let Some(nt) = iter.next() {
               buffer.push_str(format!("\"{}\"", nt).as_str());
               if iter.peek().is_some() {
                   buffer.push_str(", ");
               }
           }
           buffer.push_str(")");

        write!(f, "\"{}\" → {} {}  # {}", self.head, self.composition, buffer, self.weight)
        // write!(f, "\"{}\" → {}", self.head, self.composition)
    }
}

impl<N: fmt::Display, T: fmt::Display, W: fmt::Display> fmt::Display for PMCFG<N, T, W> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buffer = "".to_string();

        let mut iter = self.initial.iter().peekable();

        buffer.push_str("initial: [");
        while let Some(nt) = iter.next() {
            buffer.push_str(format!("\"{}\"", nt).as_str());
            if iter.peek().is_some() {
                buffer.push_str(", ");
            }
        }
        buffer.push_str("]\n\n");

        for r in &self.rules {
            buffer.push_str(format!("{}\n", r).as_str());
        }

        write!(f, "{}", buffer)
    }
}

pub fn evaluate<T: Clone + fmt::Debug>(term_map: &BTreeMap<Vec<usize>, Composition<T>>) -> Composition<T> {
    evaluate_pos(term_map, vec![])
}

pub fn evaluate_pos<T: Clone + fmt::Debug>(term_map: &BTreeMap<Vec<usize>, Composition<T>>, address: Vec<usize>) -> Composition<T> {
    let unexpanded_composition = &term_map.get(&address).unwrap().composition;
    let mut expanded_nonterminals: BTreeMap<_, Vec<Vec<VarT<T>>>> = BTreeMap::new();
    let mut expanded_composition = Vec::new();

    for component in unexpanded_composition {
        let mut expanded_component = Vec::new();

        for variable in component {
            match variable {
                &VarT::Var(num_nonter, num_compon) => {
                    if !expanded_nonterminals.contains_key(&num_nonter) {
                        let mut child_address = address.clone();
                        child_address.push(num_nonter);
                        let nonter_compos = evaluate_pos(term_map, child_address).composition;
                        expanded_nonterminals.insert(num_nonter, nonter_compos);
                    }

                    let nonter_compos = expanded_nonterminals.get(&num_nonter).unwrap();

                    if let Some(compon) = nonter_compos.get(num_compon) {
                        for terminal in compon {
                            expanded_component.push(terminal.clone());
                        }
                    } else {
                        panic!("{:?}: use of {}-th component of nonterminal {} that has only {} components!",
                               unexpanded_composition, num_compon, num_nonter, nonter_compos.len());
                    }

                },
                &VarT::T(ref terminal) => {
                    expanded_component.push(VarT::T(terminal.clone()));
                },
            }
        }

        expanded_composition.push(expanded_component);
    }

    Composition::from(expanded_composition)
}

pub fn to_term<K: Clone + cmp::Ord, H: Clone, T: Clone, W>(tree_map: &BTreeMap<K, PMCFGRule<H, T, W>>) -> (BTreeMap<K, Composition<T>>, BTreeMap<K, H>) {
    let mut term_map = BTreeMap::new();
    let mut head_map = BTreeMap::new();

    for (address, rule) in tree_map {
        let &PMCFGRule { ref head, tail: _, ref composition, weight: _ } = rule;
        term_map.insert(address.clone(), composition.clone());
        head_map.insert(address.clone(), head.clone());
    }

    (term_map, head_map)
}

#[cfg(test)]
mod tests {
    use super::*;
    use self::VarT::{Var, T};

    #[test]
    fn test_evaluate() {
        let mut term_map: BTreeMap<Vec<usize>, _> = BTreeMap::new();
        term_map.insert(vec![], Composition::from(vec![
            vec![Var(0, 0), Var(1, 0), Var(0, 1), Var(1, 1)]
        ]));
        term_map.insert(vec![0], Composition::from(vec![
            vec![Var(1, 0), Var(0, 0)],
            vec![Var(2, 0), Var(0, 1)]
        ]));
        term_map.insert(vec![0, 0], Composition::from(vec![
            vec![Var(1, 0), Var(0, 0)],
            vec![Var(2, 0), Var(0, 1)]
        ]));
        term_map.insert(vec![0, 0, 0], Composition::from(vec![
            vec![],
            vec![]
        ]));
        term_map.insert(vec![0, 0, 1], Composition::from(vec![
            vec![T('a')]
        ]));
        term_map.insert(vec![0, 0, 2], Composition::from(vec![
            vec![T('c')]
        ]));
        term_map.insert(vec![0, 1], Composition::from(vec![
            vec![T('a')]
        ]));
        term_map.insert(vec![0, 2], Composition::from(vec![
            vec![T('c')]
        ]));
        term_map.insert(vec![1], Composition::from(vec![
            vec![Var(1, 0), Var(0, 0)],
            vec![Var(2, 0), Var(0, 1)]
        ]));
        term_map.insert(vec![1, 0], Composition::from(vec![
            vec![],
            vec![]
        ]));
        term_map.insert(vec![1, 1], Composition::from(vec![
            vec![T('b')]
        ]));
        term_map.insert(vec![1, 2], Composition::from(vec![
            vec![T('d')]
        ]));

        let expanded_compos = Composition::from(vec![
            vec![T('a'), T('a'), T('b'), T('c'), T('c'), T('d')]
        ]);

        assert_eq!(expanded_compos, evaluate(&term_map));
    }

    #[test]
    #[should_panic(expected =
        "[[Var(0, 0), Var(0, 1)]]: use of 1-th component of nonterminal 0 that has only 1 components!"
    )]
    fn test_evaluate_invalid_composition() {
        let mut term_map: BTreeMap<Vec<usize>, _> = BTreeMap::new();
        term_map.insert(vec![], Composition::from(vec![
            vec![Var(0, 0), Var(0, 1)]
        ]));
        term_map.insert(vec![0], Composition::from(vec![
            vec![T('a')]
        ]));

        evaluate(&term_map);
    }

    pub fn to_dummy_pmcfg_rule<N, T>(head: N, composition: Composition<T>) -> PMCFGRule<N, T, usize> {
        PMCFGRule {
            head,
            tail: vec![],
            composition,
            weight: 0,
        }
    }

    #[test]
    fn test_to_term() {
        let compos0 = Composition::from(vec![
            vec![Var(0, 0), T("a"), Var(0, 1), T("b")]
        ]);
        let compos1 = Composition::from(vec![
            vec![Var(1, 0)],
            vec![T("c")]
        ]);
        let compos2 = Composition::from(vec![
            vec![],
            vec![]
        ]);

        let mut tree_map = BTreeMap::new();
        tree_map.insert(vec![], to_dummy_pmcfg_rule("A", compos0.clone()));
        tree_map.insert(vec![0], to_dummy_pmcfg_rule("B", compos1.clone()));
        tree_map.insert(vec![0, 1], to_dummy_pmcfg_rule("C", compos2.clone()));

        let mut term_map = BTreeMap::new();
        term_map.insert(vec![], compos0);
        term_map.insert(vec![0], compos1);
        term_map.insert(vec![0, 1], compos2);

        let mut head_map = BTreeMap::new();
        head_map.insert(vec![], "A");
        head_map.insert(vec![0], "B");
        head_map.insert(vec![0, 1], "C");

        assert_eq!((term_map, head_map), to_term(&tree_map));
    }
}
<|endoftext|>


<commit_before>//! Implementation of IRC protocol for Tokio.
<commit_msg>Implemented IrcCodec and IrcProto using LineCodec.<commit_after>//! Implementation of IRC protocol for Tokio.

use std::io;
use proto::line::LineCodec;
use proto::message::Message;
use tokio_core::io::{Codec, EasyBuf, Framed, Io};
use tokio_proto::pipeline::{ServerProto, ClientProto};

/// An IRC codec built around an inner codec.
pub struct IrcCodec<C: Codec> {
    inner: C,
}

impl IrcCodec<LineCodec> {
    /// Creates a new instance of IrcCodec wrapping a LineCodec with the specifiec encoding.
    pub fn new(label: &str) -> io::Result<IrcCodec<LineCodec>> {
        LineCodec::new(label).map(|codec| IrcCodec::from_codec(codec))
    }
}

impl<C> IrcCodec<C> where C: Codec<In = String, Out = String> {
    /// Creates a new instance of IrcCodec from the specified inner codec.
    pub fn from_codec(codec: C) -> IrcCodec<C> {
        IrcCodec { inner: codec }
    }
}

impl<C> Codec for IrcCodec<C> where C: Codec<In = String, Out = String> {
    type In = Message;
    type Out = Message;

    fn decode(&mut self, buf: &mut EasyBuf) -> io::Result<Option<Message>> {
        self.inner.decode(buf).and_then(|res| res.map_or(Ok(None), |msg| {
            msg.parse::<Message>().map(|msg| Some(msg)).map_err(|err| {
                io::Error::new(io::ErrorKind::InvalidInput, err)
            })
        }))
    }

    fn encode(&mut self, msg: Message, buf: &mut Vec<u8>) -> io::Result<()> {
        self.inner.encode(msg.to_string(), buf)
    }
}

/// Implementation of the IRC protocol backed by a line-delimited codec.
pub struct IrcProto {
    encoding_label: String,
}

impl IrcProto {
    /// Creates a new IrcProto using the specified WHATWG encoding label.
    fn new(label: &str) -> IrcProto {
        IrcProto { encoding_label: label.to_owned() }
    }
}

impl<T> ClientProto<T> for IrcProto where T: Io + 'static {
    type Request = Message;
    type Response = Message;

    type Transport = Framed<T, IrcCodec<LineCodec>>;
    type BindTransport = Result<Self::Transport, io::Error>;

    fn bind_transport(&self, io: T) -> Self::BindTransport {
        Ok(io.framed(try!(IrcCodec::new(&self.encoding_label))))
    }
}

impl<T> ServerProto<T> for IrcProto where T: Io + 'static {
    type Request = Message;
    type Response = Message;

    type Transport = Framed<T, IrcCodec<LineCodec>>;
    type BindTransport = Result<Self::Transport, io::Error>;

    fn bind_transport(&self, io: T) -> Self::BindTransport {
        Ok(io.framed(try!(IrcCodec::new(&self.encoding_label))))
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::ops::Deref;

use qvariant::*;
use types::*;
use qurl::*;
use qmeta::*;
use qmlregister::*;

extern "C" {
    fn dos_qapplication_create();
    fn dos_qapplication_exec();
    fn dos_qapplication_quit();
    fn dos_qapplication_delete();

    fn dos_qqmlapplicationengine_create() -> DosQmlApplicationEngine;
    fn dos_qqmlapplicationengine_load(vptr: DosQmlApplicationEngine, filename: DosCStr);
    fn dos_qqmlapplicationengine_load_url(vptr: DosQmlApplicationEngine, url: DosQUrl);
    fn dos_qqmlapplicationengine_load_data(vptr: DosQmlApplicationEngine, data: DosCStr);
    // fn dos_qqmlapplicationengine_add_import_path(vptr: *mut DosQQmlApplicationEngine, const char *path);
    fn dos_qqmlapplicationengine_context(vptr: DosQmlApplicationEngine) -> DosQQmlContext;
    fn dos_qqmlapplicationengine_delete(vptr: DosQmlApplicationEngine);

    fn dos_qqmlcontext_setcontextproperty(vptr: DosQQmlContext,
                                          name: DosCStr,
                                          value: DosQVariant);

}

/// Provides an entry point for building QML applications from Rust
pub struct QmlEngine {
    ptr: DosQmlApplicationEngine,
    stored: Vec<QVariant>,
    registered: HashMap<i32, CreateDObject>,
}

impl QmlEngine {
    /// Creates a QML context of a non-headless application
    pub fn new() -> Self {
        unsafe {
            dos_qapplication_create();
            QmlEngine {
                ptr: dos_qqmlapplicationengine_create(),
                stored: Vec::new(),
                registered: HashMap::new(),
            }
        }
    }

    pub fn registered_type<T: Deref<Target = QObjectMacro>>(&mut self, id: i32, registered: T) {}
    /// Loads a file as a qml file
    pub fn load_file(&self, path: &str) {
        let path_raw = ::std::env::current_dir().unwrap().join(path);
        let path = if cfg!(windows) {
            format!("file:///{}", path_raw.display())
        } else {
            format!("file://{}", path_raw.display())
        };
        unsafe { dos_qqmlapplicationengine_load_url(self.ptr, construct_qurl(&path)) }
    }

    /// Loads a string as a qml file
    pub fn load_data(&self, data: &str) {
        unsafe { dos_qqmlapplicationengine_load_data(self.ptr, stoptr(data)) }
    }

    /// Launches the application
    pub fn exec(&self) {
        unsafe {
            dos_qapplication_exec();
        }
    }
    /// Closes the application
    pub fn quit(&self) {
        unsafe {
            dos_qapplication_quit();
        }
    }

    /// Sets a property for this QML context
    ///
    /// This variant stores qvariant, so it is removed, only when this QmlEngine is removed.
    pub fn set_and_store_property<T: Into<QVariant>>(&mut self, name: &str, value: T) {
        let val = value.into();
        unsafe {
            let context = dos_qqmlapplicationengine_context(self.ptr);
            dos_qqmlcontext_setcontextproperty(context, stoptr(name), get_private_variant(&val));
        }
        self.stored.push(val);
    }

    /// Sets a property for this QML context
    pub fn set_property(&self, name: &str, value: &QVariant) {
        unsafe {
            let context = dos_qqmlapplicationengine_context(self.ptr);
            dos_qqmlcontext_setcontextproperty(context, stoptr(name), get_private_variant(value));
        }
    }
}

use utils::*;

impl Default for QmlEngine {
    fn default() -> Self {
        Self::new()
    }
}

impl Drop for QmlEngine {
    fn drop(&mut self) {
        unsafe {
            dos_qapplication_quit();
            dos_qqmlapplicationengine_delete(self.ptr);
            dos_qapplication_delete();
        }
    }
}
<commit_msg>Removed unneccessary field from qmlengine<commit_after>use std::ops::Deref;

use qvariant::*;
use types::*;
use qurl::*;
use qmeta::*;

extern "C" {
    fn dos_qapplication_create();
    fn dos_qapplication_exec();
    fn dos_qapplication_quit();
    fn dos_qapplication_delete();

    fn dos_qqmlapplicationengine_create() -> DosQmlApplicationEngine;
    fn dos_qqmlapplicationengine_load(vptr: DosQmlApplicationEngine, filename: DosCStr);
    fn dos_qqmlapplicationengine_load_url(vptr: DosQmlApplicationEngine, url: DosQUrl);
    fn dos_qqmlapplicationengine_load_data(vptr: DosQmlApplicationEngine, data: DosCStr);
    // fn dos_qqmlapplicationengine_add_import_path(vptr: *mut DosQQmlApplicationEngine, const char *path);
    fn dos_qqmlapplicationengine_context(vptr: DosQmlApplicationEngine) -> DosQQmlContext;
    fn dos_qqmlapplicationengine_delete(vptr: DosQmlApplicationEngine);

    fn dos_qqmlcontext_setcontextproperty(vptr: DosQQmlContext,
                                          name: DosCStr,
                                          value: DosQVariant);

}

/// Provides an entry point for building QML applications from Rust
pub struct QmlEngine {
    ptr: DosQmlApplicationEngine,
    stored: Vec<QVariant>,
}

impl QmlEngine {
    /// Creates a QML context of a non-headless application
    pub fn new() -> Self {
        unsafe {
            dos_qapplication_create();
            QmlEngine {
                ptr: dos_qqmlapplicationengine_create(),
                stored: Vec::new(),
            }
        }
    }

    pub fn registered_type<T: Deref<Target = QObjectMacro>>(&mut self, id: i32, registered: T) {}
    /// Loads a file as a qml file
    pub fn load_file(&self, path: &str) {
        let path_raw = ::std::env::current_dir().unwrap().join(path);
        let path = if cfg!(windows) {
            format!("file:///{}", path_raw.display())
        } else {
            format!("file://{}", path_raw.display())
        };
        unsafe { dos_qqmlapplicationengine_load_url(self.ptr, construct_qurl(&path)) }
    }

    /// Loads a string as a qml file
    pub fn load_data(&self, data: &str) {
        unsafe { dos_qqmlapplicationengine_load_data(self.ptr, stoptr(data)) }
    }

    /// Launches the application
    pub fn exec(&self) {
        unsafe {
            dos_qapplication_exec();
        }
    }
    /// Closes the application
    pub fn quit(&self) {
        unsafe {
            dos_qapplication_quit();
        }
    }

    /// Sets a property for this QML context
    ///
    /// This variant stores qvariant, so it is removed, only when this QmlEngine is removed.
    pub fn set_and_store_property<T: Into<QVariant>>(&mut self, name: &str, value: T) {
        let val = value.into();
        unsafe {
            let context = dos_qqmlapplicationengine_context(self.ptr);
            dos_qqmlcontext_setcontextproperty(context, stoptr(name), get_private_variant(&val));
        }
        self.stored.push(val);
    }

    /// Sets a property for this QML context
    pub fn set_property(&self, name: &str, value: &QVariant) {
        unsafe {
            let context = dos_qqmlapplicationengine_context(self.ptr);
            dos_qqmlcontext_setcontextproperty(context, stoptr(name), get_private_variant(value));
        }
    }
}

use utils::*;

impl Default for QmlEngine {
    fn default() -> Self {
        Self::new()
    }
}

impl Drop for QmlEngine {
    fn drop(&mut self) {
        unsafe {
            dos_qapplication_quit();
            dos_qqmlapplicationengine_delete(self.ptr);
            dos_qapplication_delete();
        }
    }
}
<|endoftext|>


<commit_before>#[cfg(not(feature = "dhcpv4"))]
include!(concat!(env!("OUT_DIR"), "/constants.rs"));

use std::collections::BTreeMap;
#[cfg(not(feature = "dhcpv4"))]
use std::convert::TryInto;
#[cfg(not(feature = "dhcpv4"))]
use std::net::Ipv4Addr;
use std::slice;

#[cfg(feature = "dhcpv4")]
use smoltcp::dhcp::Dhcpv4Client;
use smoltcp::iface::{EthernetInterfaceBuilder, NeighborCache, Routes};
#[cfg(feature = "trace")]
use smoltcp::phy::EthernetTracer;
use smoltcp::phy::{self, Device, DeviceCapabilities};
use smoltcp::socket::SocketSet;
#[cfg(feature = "dhcpv4")]
use smoltcp::socket::{RawPacketMetadata, RawSocketBuffer};
use smoltcp::time::Instant;
#[cfg(feature = "dhcpv4")]
use smoltcp::wire::Ipv4Cidr;
#[cfg(not(feature = "dhcpv4"))]
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address};
#[cfg(feature = "dhcpv4")]
use smoltcp::wire::{EthernetAddress, IpCidr, Ipv4Address};

use crate::net::NetworkInterface;

extern "Rust" {
	fn sys_get_mac_address() -> Result<[u8; 6], ()>;
	fn sys_get_mtu() -> Result<u16, ()>;
	fn sys_get_tx_buffer(len: usize) -> Result<(*mut u8, usize), ()>;
	fn sys_send_tx_buffer(handle: usize, len: usize) -> Result<(), ()>;
	fn sys_receive_rx_buffer() -> Result<(&'static mut [u8], usize), ()>;
	fn sys_rx_buffer_consumed(handle: usize) -> Result<(), ()>;
	fn sys_free_tx_buffer(handle: usize);
}

/// Data type to determine the mac address
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct HermitNet {
	pub mtu: u16,
}

impl HermitNet {
	pub fn new(mtu: u16) -> Self {
		Self { mtu }
	}
}

impl NetworkInterface<HermitNet> {
	#[cfg(feature = "dhcpv4")]
	pub fn new() -> Option<Self> {
		let mtu = match unsafe { sys_get_mtu() } {
			Ok(mtu) => mtu,
			Err(_) => {
				return None;
			}
		};
		let device = HermitNet::new(mtu);
		#[cfg(feature = "trace")]
		let device = EthernetTracer::new(device, |_timestamp, printer| {
			trace!("{}", printer);
		});

		let mac: [u8; 6] = match unsafe { sys_get_mac_address() } {
			Ok(mac) => mac,
			Err(_) => {
				return None;
			}
		};

		let neighbor_cache = NeighborCache::new(BTreeMap::new());
		let ethernet_addr = EthernetAddress([mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]]);
		let ip_addrs = [IpCidr::new(Ipv4Address::UNSPECIFIED.into(), 0)];
		let routes = Routes::new(BTreeMap::new());

		info!("MAC address {}", ethernet_addr);
		info!("MTU: {} bytes", mtu);

		let mut sockets = SocketSet::new(vec![]);
		let dhcp_rx_buffer = RawSocketBuffer::new([RawPacketMetadata::EMPTY; 1], vec![0; 900]);
		let dhcp_tx_buffer = RawSocketBuffer::new([RawPacketMetadata::EMPTY; 1], vec![0; 600]);
		let dhcp = Dhcpv4Client::new(&mut sockets, dhcp_rx_buffer, dhcp_tx_buffer, Instant::now());
		let prev_cidr = Ipv4Cidr::new(Ipv4Address::UNSPECIFIED, 0);

		let iface = EthernetInterfaceBuilder::new(device)
			.ethernet_addr(ethernet_addr)
			.neighbor_cache(neighbor_cache)
			.ip_addrs(ip_addrs)
			.routes(routes)
			.finalize();

		Some(Self {
			iface,
			sockets: sockets,
			wait_for: BTreeMap::new(),
			dhcp,
			prev_cidr,
		})
	}

	#[cfg(not(feature = "dhcpv4"))]
	pub fn new() -> Option<Self> {
		let mtu = match unsafe { sys_get_mtu() } {
			Ok(mtu) => mtu,
			Err(_) => {
				return None;
			}
		};
		let device = HermitNet::new(mtu);
		#[cfg(feature = "trace")]
		let device = EthernetTracer::new(device, |_timestamp, printer| {
			trace!("{}", printer);
		});

		let mac: [u8; 6] = match unsafe { sys_get_mac_address() } {
			Ok(mac) => mac,
			Err(_) => {
				return None;
			}
		};
		let myip: Ipv4Addr = HERMIT_IP.parse().expect("Unable to parse IPv4 address");
		let myip = myip.octets();
		let mygw: Ipv4Addr = HERMIT_GATEWAY
			.parse()
			.expect("Unable to parse IPv4 address");
		let mygw = mygw.octets();
		let mymask: Ipv4Addr = HERMIT_MASK.parse().expect("Unable to parse IPv4 address");
		let mymask = mymask.octets();

		// calculate the netmask length
		// => count the number of contiguous 1 bits,
		// starting at the most significant bit in the first octet
		let mut prefix_len = (!mymask[0]).trailing_zeros();
		if prefix_len == 8 {
			prefix_len += (!mymask[1]).trailing_zeros();
		}
		if prefix_len == 16 {
			prefix_len += (!mymask[2]).trailing_zeros();
		}
		if prefix_len == 24 {
			prefix_len += (!mymask[3]).trailing_zeros();
		}

		let neighbor_cache = NeighborCache::new(BTreeMap::new());
		let ethernet_addr = EthernetAddress([mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]]);
		let ip_addrs = [IpCidr::new(
			IpAddress::v4(myip[0], myip[1], myip[2], myip[3]),
			prefix_len.try_into().unwrap(),
		)];
		let default_v4_gw = Ipv4Address::new(mygw[0], mygw[1], mygw[2], mygw[3]);
		let mut routes = Routes::new(BTreeMap::new());
		routes.add_default_ipv4_route(default_v4_gw).unwrap();

		info!("MAC address {}", ethernet_addr);
		info!("Configure network interface with address {}", ip_addrs[0]);
		info!("Configure gateway with address {}", default_v4_gw);
		info!("MTU: {} bytes", mtu);

		let iface = EthernetInterfaceBuilder::new(device)
			.ethernet_addr(ethernet_addr)
			.neighbor_cache(neighbor_cache)
			.ip_addrs(ip_addrs)
			.routes(routes)
			.finalize();

		Some(Self {
			iface,
			sockets: SocketSet::new(vec![]),
			wait_for: BTreeMap::new(),
		})
	}
}

impl<'a> Device<'a> for HermitNet {
	type RxToken = RxToken;
	type TxToken = TxToken;

	fn capabilities(&self) -> DeviceCapabilities {
		let mut cap = DeviceCapabilities::default();
		cap.max_transmission_unit = self.mtu.into();
		cap
	}

	fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
		match unsafe { sys_receive_rx_buffer() } {
			Ok((buffer, handle)) => Some((RxToken::new(buffer, handle), TxToken::new())),
			_ => None,
		}
	}

	fn transmit(&'a mut self) -> Option<Self::TxToken> {
		trace!("create TxToken to transfer data");
		Some(TxToken::new())
	}
}

#[doc(hidden)]
pub struct RxToken {
	buffer: &'static mut [u8],
	handle: usize,
}

impl RxToken {
	pub fn new(buffer: &'static mut [u8], handle: usize) -> Self {
		Self { buffer, handle }
	}
}

impl phy::RxToken for RxToken {
	#[allow(unused_mut)]
	fn consume<R, F>(mut self, _timestamp: Instant, f: F) -> smoltcp::Result<R>
	where
		F: FnOnce(&mut [u8]) -> smoltcp::Result<R>,
	{
		let result = f(self.buffer);
		if unsafe { sys_rx_buffer_consumed(self.handle).is_ok() } {
			result
		} else {
			Err(smoltcp::Error::Exhausted)
		}
	}
}

#[doc(hidden)]
pub struct TxToken;

impl TxToken {
	pub fn new() -> Self {
		Self {}
	}
}

impl phy::TxToken for TxToken {
	fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> smoltcp::Result<R>
	where
		F: FnOnce(&mut [u8]) -> smoltcp::Result<R>,
	{
		let (tx_buffer, handle) =
			unsafe { sys_get_tx_buffer(len).map_err(|_| smoltcp::Error::Exhausted)? };
		let tx_slice: &'static mut [u8] = unsafe { slice::from_raw_parts_mut(tx_buffer, len) };
		match f(tx_slice) {
			Ok(result) => {
				if unsafe { sys_send_tx_buffer(handle, len).is_ok() } {
					Ok(result)
				} else {
					Err(smoltcp::Error::Exhausted)
				}
			}
			Err(e) => {
				unsafe { sys_free_tx_buffer(handle) };
				Err(e)
			}
		}
	}
}
<commit_msg>increasing the readability<commit_after>#[cfg(not(feature = "dhcpv4"))]
include!(concat!(env!("OUT_DIR"), "/constants.rs"));

use std::collections::BTreeMap;
#[cfg(not(feature = "dhcpv4"))]
use std::convert::TryInto;
#[cfg(not(feature = "dhcpv4"))]
use std::net::Ipv4Addr;
use std::slice;

#[cfg(feature = "dhcpv4")]
use smoltcp::dhcp::Dhcpv4Client;
use smoltcp::iface::{EthernetInterfaceBuilder, NeighborCache, Routes};
#[cfg(feature = "trace")]
use smoltcp::phy::EthernetTracer;
use smoltcp::phy::{self, Device, DeviceCapabilities};
use smoltcp::socket::SocketSet;
#[cfg(feature = "dhcpv4")]
use smoltcp::socket::{RawPacketMetadata, RawSocketBuffer};
use smoltcp::time::Instant;
#[cfg(not(feature = "dhcpv4"))]
use smoltcp::wire::IpAddress;
#[cfg(feature = "dhcpv4")]
use smoltcp::wire::Ipv4Cidr;
use smoltcp::wire::{EthernetAddress, IpCidr, Ipv4Address};

use crate::net::NetworkInterface;

extern "Rust" {
	fn sys_get_mac_address() -> Result<[u8; 6], ()>;
	fn sys_get_mtu() -> Result<u16, ()>;
	fn sys_get_tx_buffer(len: usize) -> Result<(*mut u8, usize), ()>;
	fn sys_send_tx_buffer(handle: usize, len: usize) -> Result<(), ()>;
	fn sys_receive_rx_buffer() -> Result<(&'static mut [u8], usize), ()>;
	fn sys_rx_buffer_consumed(handle: usize) -> Result<(), ()>;
	fn sys_free_tx_buffer(handle: usize);
}

/// Data type to determine the mac address
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct HermitNet {
	pub mtu: u16,
}

impl HermitNet {
	pub fn new(mtu: u16) -> Self {
		Self { mtu }
	}
}

impl NetworkInterface<HermitNet> {
	#[cfg(feature = "dhcpv4")]
	pub fn new() -> Option<Self> {
		let mtu = match unsafe { sys_get_mtu() } {
			Ok(mtu) => mtu,
			Err(_) => {
				return None;
			}
		};
		let device = HermitNet::new(mtu);
		#[cfg(feature = "trace")]
		let device = EthernetTracer::new(device, |_timestamp, printer| {
			trace!("{}", printer);
		});

		let mac: [u8; 6] = match unsafe { sys_get_mac_address() } {
			Ok(mac) => mac,
			Err(_) => {
				return None;
			}
		};

		let neighbor_cache = NeighborCache::new(BTreeMap::new());
		let ethernet_addr = EthernetAddress([mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]]);
		let ip_addrs = [IpCidr::new(Ipv4Address::UNSPECIFIED.into(), 0)];
		let routes = Routes::new(BTreeMap::new());

		info!("MAC address {}", ethernet_addr);
		info!("MTU: {} bytes", mtu);

		let mut sockets = SocketSet::new(vec![]);
		let dhcp_rx_buffer = RawSocketBuffer::new([RawPacketMetadata::EMPTY; 1], vec![0; 900]);
		let dhcp_tx_buffer = RawSocketBuffer::new([RawPacketMetadata::EMPTY; 1], vec![0; 600]);
		let dhcp = Dhcpv4Client::new(&mut sockets, dhcp_rx_buffer, dhcp_tx_buffer, Instant::now());
		let prev_cidr = Ipv4Cidr::new(Ipv4Address::UNSPECIFIED, 0);

		let iface = EthernetInterfaceBuilder::new(device)
			.ethernet_addr(ethernet_addr)
			.neighbor_cache(neighbor_cache)
			.ip_addrs(ip_addrs)
			.routes(routes)
			.finalize();

		Some(Self {
			iface,
			sockets: sockets,
			wait_for: BTreeMap::new(),
			dhcp,
			prev_cidr,
		})
	}

	#[cfg(not(feature = "dhcpv4"))]
	pub fn new() -> Option<Self> {
		let mtu = match unsafe { sys_get_mtu() } {
			Ok(mtu) => mtu,
			Err(_) => {
				return None;
			}
		};
		let device = HermitNet::new(mtu);
		#[cfg(feature = "trace")]
		let device = EthernetTracer::new(device, |_timestamp, printer| {
			trace!("{}", printer);
		});

		let mac: [u8; 6] = match unsafe { sys_get_mac_address() } {
			Ok(mac) => mac,
			Err(_) => {
				return None;
			}
		};
		let myip: Ipv4Addr = HERMIT_IP.parse().expect("Unable to parse IPv4 address");
		let myip = myip.octets();
		let mygw: Ipv4Addr = HERMIT_GATEWAY
			.parse()
			.expect("Unable to parse IPv4 address");
		let mygw = mygw.octets();
		let mymask: Ipv4Addr = HERMIT_MASK.parse().expect("Unable to parse IPv4 address");
		let mymask = mymask.octets();

		// calculate the netmask length
		// => count the number of contiguous 1 bits,
		// starting at the most significant bit in the first octet
		let mut prefix_len = (!mymask[0]).trailing_zeros();
		if prefix_len == 8 {
			prefix_len += (!mymask[1]).trailing_zeros();
		}
		if prefix_len == 16 {
			prefix_len += (!mymask[2]).trailing_zeros();
		}
		if prefix_len == 24 {
			prefix_len += (!mymask[3]).trailing_zeros();
		}

		let neighbor_cache = NeighborCache::new(BTreeMap::new());
		let ethernet_addr = EthernetAddress([mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]]);
		let ip_addrs = [IpCidr::new(
			IpAddress::v4(myip[0], myip[1], myip[2], myip[3]),
			prefix_len.try_into().unwrap(),
		)];
		let default_v4_gw = Ipv4Address::new(mygw[0], mygw[1], mygw[2], mygw[3]);
		let mut routes = Routes::new(BTreeMap::new());
		routes.add_default_ipv4_route(default_v4_gw).unwrap();

		info!("MAC address {}", ethernet_addr);
		info!("Configure network interface with address {}", ip_addrs[0]);
		info!("Configure gateway with address {}", default_v4_gw);
		info!("MTU: {} bytes", mtu);

		let iface = EthernetInterfaceBuilder::new(device)
			.ethernet_addr(ethernet_addr)
			.neighbor_cache(neighbor_cache)
			.ip_addrs(ip_addrs)
			.routes(routes)
			.finalize();

		Some(Self {
			iface,
			sockets: SocketSet::new(vec![]),
			wait_for: BTreeMap::new(),
		})
	}
}

impl<'a> Device<'a> for HermitNet {
	type RxToken = RxToken;
	type TxToken = TxToken;

	fn capabilities(&self) -> DeviceCapabilities {
		let mut cap = DeviceCapabilities::default();
		cap.max_transmission_unit = self.mtu.into();
		cap
	}

	fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
		match unsafe { sys_receive_rx_buffer() } {
			Ok((buffer, handle)) => Some((RxToken::new(buffer, handle), TxToken::new())),
			_ => None,
		}
	}

	fn transmit(&'a mut self) -> Option<Self::TxToken> {
		trace!("create TxToken to transfer data");
		Some(TxToken::new())
	}
}

#[doc(hidden)]
pub struct RxToken {
	buffer: &'static mut [u8],
	handle: usize,
}

impl RxToken {
	pub fn new(buffer: &'static mut [u8], handle: usize) -> Self {
		Self { buffer, handle }
	}
}

impl phy::RxToken for RxToken {
	#[allow(unused_mut)]
	fn consume<R, F>(mut self, _timestamp: Instant, f: F) -> smoltcp::Result<R>
	where
		F: FnOnce(&mut [u8]) -> smoltcp::Result<R>,
	{
		let result = f(self.buffer);
		if unsafe { sys_rx_buffer_consumed(self.handle).is_ok() } {
			result
		} else {
			Err(smoltcp::Error::Exhausted)
		}
	}
}

#[doc(hidden)]
pub struct TxToken;

impl TxToken {
	pub fn new() -> Self {
		Self {}
	}
}

impl phy::TxToken for TxToken {
	fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> smoltcp::Result<R>
	where
		F: FnOnce(&mut [u8]) -> smoltcp::Result<R>,
	{
		let (tx_buffer, handle) =
			unsafe { sys_get_tx_buffer(len).map_err(|_| smoltcp::Error::Exhausted)? };
		let tx_slice: &'static mut [u8] = unsafe { slice::from_raw_parts_mut(tx_buffer, len) };
		match f(tx_slice) {
			Ok(result) => {
				if unsafe { sys_send_tx_buffer(handle, len).is_ok() } {
					Ok(result)
				} else {
					Err(smoltcp::Error::Exhausted)
				}
			}
			Err(e) => {
				unsafe { sys_free_tx_buffer(handle) };
				Err(e)
			}
		}
	}
}
<|endoftext|>


<commit_before>//! [β-reduction](https://en.wikipedia.org/wiki/Beta_normal_form) for lambda `Term`s

use term::*;
use term::Term::*;
use self::Closure::*;
use self::Expression::*;
use std::collections::VecDeque;

#[derive(Debug, PartialEq, Clone)]
enum Closure {
    Depth(usize),
    TermInEnv(Term, Environment)
}

#[derive(Debug, PartialEq)]
enum Expression {
    Evaluation(Closure),
    Application(Box<Expression>, Term, Environment)
}

type Environment = VecDeque<Closure>;

fn whnf(term: Term, mut env: Environment) -> Expression {
    match term {
        Var(i) => match env.remove(i - 1) {
            Some(Depth(i)) => Evaluation(Depth(i)),
            Some(TermInEnv(t, e)) => whnf(t, e),
            None => unreachable!()
        },
        Abs(t) => Evaluation(TermInEnv(Abs(t), env)),
        App(lhs, rhs) => match whnf(*lhs, env.clone()) { // TODO: try to remove this clone()
            Evaluation(TermInEnv(Abs(lhs2), mut env2)) => {
                env2.push_front(TermInEnv(*rhs, env));
                whnf(*lhs2, env2)
            },
            expr => Application(Box::new(expr), *rhs, env)
        }
    }
}

fn reduce(depth: usize, exp: Expression) -> Term {
    match exp {
        Application(lhs, rhs, env) => app(reduce(depth, *lhs), nf(depth, rhs, env)),
        Evaluation(TermInEnv(Abs(term), mut env)) => {
            env.push_front(Depth(depth));
            abs(nf(depth + 1, *term, env))
        },
        Evaluation(TermInEnv(term, _)) => term,
        Evaluation(Depth(i)) => Var(depth - i)
    }
}

fn nf(depth: usize, term: Term, env: Environment) -> Term {
    reduce(depth, whnf(term, env))
}

/// Returns a term reduced to its normal form. Consumes its argument.
///
/// # Example
///
/// ```
/// use lambda_calculus::booleans::{if_else, tru};
/// use lambda_calculus::arithmetic::{zero, one, succ};
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(succ().app(zero())), one());
/// assert_eq!(normalize(if_else().app(tru()).app(one()).app(zero())), one());
/// ```
pub fn normalize(term: Term) -> Term {
    nf(0, term, VecDeque::new())
}

/// Set to `true` to see all the steps of β-reductions. The default is `false`.
pub const SHOW_REDUCTIONS: bool = true;

impl Term {
    /// Performs a single normal-order β-reduction on `self`.
    ///
    /// # Example
    ///
    /// ```
    /// use lambda_calculus::arithmetic::succ;
    ///
    /// // SUCC := λ λ λ 2 (3 2 1), ONE := λ λ 2 1
    /// let mut succ_one = succ().app(1.into());
    /// succ_one.beta_once();
    ///
    /// assert_eq!(&*format!("{}", succ_one), "λλ2((λλ21)21)");
    /// ```
    pub fn beta_once(&mut self) {
        match *self {
            Var(_) => (),
            Abs(_) => self.unabs_ref_mut().unwrap().beta_once(),
            App(_, _) => {
                let copy = self.clone();
                if let Ok(result) = copy.eval() {
                    if SHOW_REDUCTIONS { println!("    {} reduces to {}", self, result) }
                    *self = result
                } else if self.lhs_ref().unwrap().unvar_ref().is_err() {
                    self.lhs_ref_mut().unwrap().beta_once()
                } else {
                    self.rhs_ref_mut().unwrap().beta_once()
                }
            }
        }
    }

    /// Performs full normal-order β-reduction on `self`.
    ///
    /// # Example
    ///
    /// ```
    /// use lambda_calculus::arithmetic::pred;
    ///
    /// // PRED := λ λ λ 3 (λ λ 1 (2 4)) (λ 2) (λ 1), ONE := λ λ 2 1
    /// let mut pred_one = pred().app(1.into());
    /// pred_one.beta_full();
    ///
    /// assert_eq!(&*format!("{}", pred_one), "λλ1");
    /// ```
    pub fn beta_full(&mut self) {
        if SHOW_REDUCTIONS { println!("reducing {}", self) }
        let mut tmp = self.clone();
        self.beta_once();

        while tmp != *self {
            tmp = self.clone();
            if SHOW_REDUCTIONS { println!("reducing {}", self) }
            self.beta_once();
        }

        if SHOW_REDUCTIONS { println!("    doesn't reduce") }
    }
}

#[cfg(test)]
mod test {

    #[test]
    fn weak_head_normal_form() {
        // TODO
    }
}
<commit_msg>Add "standalone" beta reduction functions<commit_after>//! [β-reduction](https://en.wikipedia.org/wiki/Beta_normal_form) for lambda `Term`s

use term::*;
use term::Term::*;
use self::Closure::*;
use self::Expression::*;
use std::collections::VecDeque;

#[derive(Debug, PartialEq, Clone)]
enum Closure {
    Depth(usize),
    TermInEnv(Term, Environment)
}

#[derive(Debug, PartialEq)]
enum Expression {
    Evaluation(Closure),
    Application(Box<Expression>, Term, Environment)
}

type Environment = VecDeque<Closure>;

fn whnf(term: Term, mut env: Environment) -> Expression {
    match term {
        Var(i) => match env.remove(i - 1) {
            Some(Depth(i)) => Evaluation(Depth(i)),
            Some(TermInEnv(t, e)) => whnf(t, e),
            None => unreachable!()
        },
        Abs(t) => Evaluation(TermInEnv(Abs(t), env)),
        App(lhs, rhs) => match whnf(*lhs, env.clone()) { // TODO: try to remove this clone()
            Evaluation(TermInEnv(Abs(lhs2), mut env2)) => {
                env2.push_front(TermInEnv(*rhs, env));
                whnf(*lhs2, env2)
            },
            expr => Application(Box::new(expr), *rhs, env)
        }
    }
}

fn reduce(depth: usize, exp: Expression) -> Term {
    match exp {
        Application(lhs, rhs, env) => app(reduce(depth, *lhs), nf(depth, rhs, env)),
        Evaluation(TermInEnv(Abs(term), mut env)) => {
            env.push_front(Depth(depth));
            abs(nf(depth + 1, *term, env))
        },
        Evaluation(TermInEnv(term, _)) => term,
        Evaluation(Depth(i)) => Var(depth - i)
    }
}

fn nf(depth: usize, term: Term, env: Environment) -> Term {
    reduce(depth, whnf(term, env))
}

/// Returns a term reduced to its normal form. Consumes its argument.
///
/// # Example
///
/// ```
/// use lambda_calculus::booleans::{if_else, tru};
/// use lambda_calculus::arithmetic::{zero, one, succ};
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(succ().app(zero())), one());
/// assert_eq!(normalize(if_else().app(tru()).app(one()).app(zero())), one());
/// ```
pub fn normalize(term: Term) -> Term {
    nf(0, term, VecDeque::new())
}

/// Set to `true` to see all the steps of β-reductions. The default is `false`.
pub const SHOW_REDUCTIONS: bool = false;

impl Term {
    /// Performs a single normal-order β-reduction on `self`.
    ///
    /// # Example
    ///
    /// ```
    /// use lambda_calculus::arithmetic::succ;
    ///
    /// // SUCC := λ λ λ 2 (3 2 1), ONE := λ λ 2 1
    /// let mut succ_one = succ().app(1.into());
    /// succ_one.beta_once();
    ///
    /// assert_eq!(&*format!("{}", succ_one), "λλ2((λλ21)21)");
    /// ```
    pub fn beta_once(&mut self) {
        match *self {
            Var(_) => (),
            Abs(_) => self.unabs_ref_mut().unwrap().beta_once(),
            App(_, _) => {
                let copy = self.clone();
                if let Ok(result) = copy.eval() {
                    if SHOW_REDUCTIONS { println!("    {} reduces to {}", self, result) }
                    *self = result
                } else if self.lhs_ref().unwrap().unvar_ref().is_err() {
                    self.lhs_ref_mut().unwrap().beta_once()
                } else {
                    self.rhs_ref_mut().unwrap().beta_once()
                }
            }
        }
    }

    /// Performs full normal-order β-reduction on `self`.
    ///
    /// # Example
    ///
    /// ```
    /// use lambda_calculus::arithmetic::pred;
    ///
    /// let mut pred_one = pred().app(1.into());
    /// pred_one.beta_full();
    ///
    /// assert_eq!(pred_one, 0.into());
    /// ```
    pub fn beta_full(&mut self) {
        if SHOW_REDUCTIONS { println!("reducing {}", self) }
        let mut tmp = self.clone();
        self.beta_once();

        while tmp != *self {
            tmp = self.clone();
            if SHOW_REDUCTIONS { println!("reducing {}", self) }
            self.beta_once();
        }

        if SHOW_REDUCTIONS { println!("    doesn't reduce") }
    }
}

/// Performs full normal-order β-reduction on a `Term`, consuming it in the process.
///
/// # Example
///
/// ```
/// use lambda_calculus::arithmetic::pred;
/// use lambda_calculus::reduction::beta_full;
///
/// let pred_one = pred().app(1.into());
///
/// assert_eq!(beta_full(pred_one), 0.into());
/// ```
pub fn beta_full(mut term: Term) -> Term {
    term.beta_full();
    term
}

/// Performs a single normal-order β-reduction on `self`.
///
/// # Example
///
/// ```
/// use lambda_calculus::arithmetic::succ;
/// use lambda_calculus::reduction::beta_once;
///
/// // SUCC := λ λ λ 2 (3 2 1), ONE := λ λ 2 1
/// let succ_one = succ().app(1.into());
///
/// assert_eq!(&*format!("{}", beta_once(succ_one)), "λλ2((λλ21)21)");
/// ```
pub fn beta_once(mut term: Term) -> Term {
    term.beta_once();
    term
}

#[cfg(test)]
mod test {

    #[test]
    fn weak_head_normal_form() {
        // TODO
    }
}
<|endoftext|>


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

//! A wrapper around another RNG that reseeds it after it
//! generates a certain number of random bytes.

use {Rng, SeedableRng, Error};

/// A wrapper around any RNG which reseeds the underlying RNG after it
/// has generated a certain number of random bytes.
#[derive(Debug)]
pub struct ReseedingRng<R, Rsdr> {
    rng: R,
    generation_threshold: u64,
    bytes_generated: u64,
    /// Controls the behaviour when reseeding the RNG.
    reseeder: Rsdr,
}

impl<R: Rng+SeedableRng, Rsdr: Rng> ReseedingRng<R, Rsdr> {
    /// Create a new `ReseedingRng` with the given parameters.
    ///
    /// # Arguments
    ///
    /// * `rng`: the random number generator to use.
    /// * `generation_threshold`: the number of bytes of entropy at which to reseed the RNG.
    /// * `reseeder`: the reseeding object to use.
    pub fn new(rng: R, generation_threshold: u64, reseeder: Rsdr) -> ReseedingRng<R,Rsdr> {
        ReseedingRng {
            rng: rng,
            generation_threshold: generation_threshold,
            bytes_generated: 0,
            reseeder: reseeder
        }
    }

    /// Reseed the internal RNG if the number of bytes that have been
    /// generated exceed the threshold.
    pub fn reseed_if_necessary(&mut self) {
        if self.bytes_generated >= self.generation_threshold {
            trace!("Reseeding RNG after {} bytes", self.bytes_generated);
            R::from_rng(&mut self.reseeder).map(|result| self.rng = result)
                    .unwrap_or_else(|err| panic!("reseeding failed: {}", err));
            self.bytes_generated = 0;
        }
    }
}

impl<R: Rng+SeedableRng, Rsdr: Rng> Rng for ReseedingRng<R, Rsdr> {
    fn next_u32(&mut self) -> u32 {
        self.reseed_if_necessary();
        self.bytes_generated += 4;
        self.rng.next_u32()
    }

    fn next_u64(&mut self) -> u64 {
        self.reseed_if_necessary();
        self.bytes_generated += 8;
        self.rng.next_u64()
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        self.reseed_if_necessary();
        self.bytes_generated += dest.len() as u64;
        self.rng.fill_bytes(dest)
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        self.reseed_if_necessary();
        self.bytes_generated += dest.len() as u64;
        self.rng.try_fill_bytes(dest)
    }
}

#[cfg(test)]
mod test {
    use {impls, le};
    use super::{ReseedingRng};
    use {SeedableRng, Rng, Error};

    struct Counter {
        i: u32
    }

    impl Rng for Counter {
        fn next_u32(&mut self) -> u32 {
            self.i += 1;
            // very random
            self.i - 1
        }
        fn next_u64(&mut self) -> u64 {
            impls::next_u64_via_u32(self)
        }

        fn fill_bytes(&mut self, dest: &mut [u8]) {
            impls::fill_bytes_via_u64(self, dest)
        }
    }
    impl SeedableRng for Counter {
        type Seed = [u8; 4];
        fn from_seed(seed: Self::Seed) -> Self {
            let mut seed_u32 = [0u32; 1];
            le::read_u32_into(&seed, &mut seed_u32);
            Counter { i: seed_u32[0] }
        }
    }

    #[derive(Debug, Clone)]
    struct ResetCounter;
    impl Rng for ResetCounter {
        fn next_u32(&mut self) -> u32 { unimplemented!() }
        fn next_u64(&mut self) -> u64 { unimplemented!() }
        fn fill_bytes(&mut self, _dest: &mut [u8]) { unimplemented!() }
        fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
            for i in dest.iter_mut() { *i = 0; }
            Ok(())
        }
    }

    #[test]
    fn test_reseeding() {
        let mut rs = ReseedingRng::new(Counter {i:0}, 400, ResetCounter);

        let mut i = 0;
        for _ in 0..1000 {
            assert_eq!(rs.next_u32(), i % 100);
            i += 1;
        }
    }
}
<commit_msg>Port ReseedingRng changes<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A wrapper around another PRNG that reseeds it after it
//! generates a certain number of random bytes.

use {Rng, SeedableRng, Error, ErrorKind};

/// A wrapper around any PRNG which reseeds the underlying PRNG after it has
/// generated a certain number of random bytes.
///
/// Reseeding is never strictly *necessary*. Cryptographic PRNGs don't have a
/// limited number of bytes they can output, or at least not a limit reachable
/// in any practical way. There is no such thing as 'running out of entropy'.
///
/// Some small non-cryptographic PRNG's can have very small periods of for
/// example less than 264. Would reseeding help to ensure that you do
/// not wrap around at the end of the period? A period of 264 still
/// takes several centuries of CPU-years on current hardware. Reseeding will
/// actually make things worse, because the reseeded PRNG will just continue
/// somewhere else *in the same period*, with a high chance of overlapping with
/// previously used parts of it.
///
/// # When should you use `ReseedingRng`?
///
/// - Reseeding can be seen as some form of 'security in depth'. Even if in the
///   future there is found a cryptographic weakness in the used CSPRNG,
///   occasionally reseeding should make exploiting it much more difficult or
///   even impossible.
/// - It can be used as a poor man's cryptography (not recommended, just use a
///   good CSPRNG). Previous implementations of `thread_rng` for example used
///   `ReseedingRng` with the ISAAC RNG. That algorithm, although seemingly
///   strong, does not come with a security proof and does not meet the current
///   standards for a cryptographically secure PRNG. By reseeding it very
///   frequently (every 32 MiB) it seems safe to assume there is no attack that
///   can operate on the tiny window between reseeds.
///
/// # Error handling
///
/// If reseeding fails, `try_fill_bytes` is the only `Rng` method to report it.
/// For all other methods `ReseedingRng` wil not panic, but try to handle the
/// error intelligently. And if nothing helps, continue without reseeding.
///
/// It is usually best to use the infallible methods `next_u32`, `next_u64` and
/// `fill_bytes` because they can make use of this error handeling strategy.
///
/// Use `try_fill_bytes` and possible `try_reseed` if you want to handle
/// reseeding errors explicitly. All reseeding errors will either be
/// `ErrorKind::Transient` or `ErrorKind::NotReady`, and contain the original
/// error as cause.
#[derive(Debug)]
pub struct ReseedingRng<R, Rsdr> {
    rng: R,
    reseeder: Rsdr,
    threshold: i64,
    bytes_until_reseed: i64,
}

impl<R: Rng+SeedableRng, Rsdr: Rng> ReseedingRng<R, Rsdr> {
    /// Create a new `ReseedingRng` with the given parameters.
    ///
    /// # Arguments
    ///
    /// * `rng`: the random number generator to use.
    /// * `threshold`: the number of generated bytes after which to reseed the RNG.
    /// * `reseeder`: the RNG to use for reseeding.
    pub fn new(rng: R, threshold: u64, reseeder: Rsdr) -> ReseedingRng<R,Rsdr> {
        assert!(threshold <= ::core::i64::MAX as u64);
        ReseedingRng {
            rng: rng,
            reseeder: reseeder,
            threshold: threshold as i64,
            bytes_until_reseed: threshold as i64,
        }
    }

    /// Reseed the internal RNG.
    ///
    /// On error, this will try to intelligently handle reseeding. If the error
    /// kind indicates retrying might help, it will immidiately retry a couple
    /// of times. If the error kind indicates the seeding RNG is not ready, it
    /// will retry after a while, after `threshold / 256` generated bytes.
    ///
    /// If the seeding RNG has an other error or a permanently failure, it will
    /// completely skip reseeding. Only after generating `threshold` bytes it
    /// will retry again.
    #[inline(never)]
    pub fn reseed(&mut self) {
        trace!("Reseeding RNG after {} generated bytes",
               self.threshold - self.bytes_until_reseed);
        self.bytes_until_reseed = self.threshold;
        let mut err_count = 0;
        loop {
            if let Err(e) = R::from_rng(&mut self.reseeder)
                            .map(|result| self.rng = result) {
                let kind = e.kind();
                if kind.should_wait() {
                    self.bytes_until_reseed = self.threshold >> 8;
                    info!("Reseeding delayed, retrying after {} generated bytes",
                           self.bytes_until_reseed);
                } else if kind.should_retry() {
                    err_count += 1;
                    // Retry immediately for 5 times (arbitrary limit)
                    if err_count <= 5 { continue; }
                }
                info!("Reseeding failed, RNG remains unchanged. Error: {}", e);
            }
            break; // Successfully reseeded, delayed, or given up.
        }
    }

    /// Reseed the internal RNG if the number of bytes that have been
    /// generated exceed the threshold.
    ///
    /// If reseeding fails, return an error with the original cause. Note that
    /// if the cause has a permanent failure, we report a transient error and
    /// skip reseeding.
    #[inline(never)]
    pub fn try_reseed(&mut self) -> Result<(), Error> {
        trace!("Reseeding RNG after {} generated bytes",
               self.threshold - self.bytes_until_reseed);
        if let Err(err) = R::from_rng(&mut self.reseeder)
                          .map(|result| self.rng = result) {
            let newkind = match err.kind() {
                a @ ErrorKind::NotReady => a,
                b @ ErrorKind::Transient => b,
                _ => {
                    self.bytes_until_reseed = self.threshold; // skip reseeding
                    ErrorKind::Transient
                }
            };
            return Err(Error::with_cause(newkind, "reseeding failed", err));
        }
        self.bytes_until_reseed = self.threshold;
        Ok(())
    }
}

impl<R: Rng+SeedableRng, Rsdr: Rng> Rng for ReseedingRng<R, Rsdr> {
    fn next_u32(&mut self) -> u32 {
        let value = self.rng.next_u32();
        self.bytes_until_reseed -= 4;
        if self.bytes_until_reseed <= 0 {
            self.reseed();
        }
        value
    }

    fn next_u64(&mut self) -> u64 {
        let value = self.rng.next_u64();
        self.bytes_until_reseed -= 8;
        if self.bytes_until_reseed <= 0 {
            self.reseed();
        }
        value
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        self.rng.fill_bytes(dest);
        self.bytes_until_reseed -= dest.len() as i64;
        if self.bytes_until_reseed <= 0 {
            self.reseed();
        }
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        self.rng.try_fill_bytes(dest)?;
        self.bytes_until_reseed -= dest.len() as i64;
        if self.bytes_until_reseed <= 0 {
            self.try_reseed()?;
        }
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use {impls, le};
    use super::{ReseedingRng};
    use {SeedableRng, Rng, Error};

    struct Counter {
        i: u32
    }

    impl Rng for Counter {
        fn next_u32(&mut self) -> u32 {
            self.i += 1;
            // very random
            self.i - 1
        }
        fn next_u64(&mut self) -> u64 {
            impls::next_u64_via_u32(self)
        }

        fn fill_bytes(&mut self, dest: &mut [u8]) {
            impls::fill_bytes_via_u64(self, dest)
        }
    }
    impl SeedableRng for Counter {
        type Seed = [u8; 4];
        fn from_seed(seed: Self::Seed) -> Self {
            let mut seed_u32 = [0u32; 1];
            le::read_u32_into(&seed, &mut seed_u32);
            Counter { i: seed_u32[0] }
        }
    }

    #[derive(Debug, Clone)]
    struct ResetCounter;
    impl Rng for ResetCounter {
        fn next_u32(&mut self) -> u32 { unimplemented!() }
        fn next_u64(&mut self) -> u64 { unimplemented!() }
        fn fill_bytes(&mut self, _dest: &mut [u8]) { unimplemented!() }
        fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
            for i in dest.iter_mut() { *i = 0; }
            Ok(())
        }
    }

    #[test]
    fn test_reseeding() {
        let mut rs = ReseedingRng::new(Counter {i:0}, 400, ResetCounter);

        let mut i = 0;
        for _ in 0..1000 {
            assert_eq!(rs.next_u32(), i % 100);
            i += 1;
        }
    }
}
<|endoftext|>


<commit_before>use super::*;
use crate::types::Call;
use crate::vim;
use crossbeam_channel::{bounded, unbounded, Receiver, Sender};

#[derive(Clone, Serialize)]
pub struct RpcClient {
    languageId: LanguageId,
    // TODO: make atomic.
    #[serde(skip_serializing)]
    id: Arc<Mutex<Id>>,
    #[serde(skip_serializing)]
    writer_tx: Sender<vim::RawMessage>,
    #[serde(skip_serializing)]
    reader_tx: Sender<(Id, Sender<rpc::Output>)>,
    pub process_id: Option<u32>,
}

impl RpcClient {
    #[allow(clippy::new_ret_no_self)]
    pub fn new(
        languageId: LanguageId,
        reader: impl BufRead + Send + 'static,
        writer: impl Write + Send + 'static,
        process_id: Option<u32>,
        sink: Sender<Call>,
    ) -> Fallible<Self> {
        let (reader_tx, reader_rx): (Sender<(Id, Sender<rpc::Output>)>, _) = unbounded();

        let languageId_clone = languageId.clone();
        let reader_thread_name = format!("reader-{:?}", languageId);
        thread::Builder::new()
            .name(reader_thread_name.clone())
            .spawn(move || {
                if let Err(err) = loop_read(reader, reader_rx, sink, languageId_clone) {
                    error!("Thread {} exited with error: {:?}", reader_thread_name, err);
                }
            })?;

        let (writer_tx, writer_rx) = unbounded();
        let writer_thread_name = format!("writer-{:?}", languageId);
        let languageId_clone = languageId.clone();
        thread::Builder::new()
            .name(writer_thread_name.clone())
            .spawn(move || {
                if let Err(err) = loop_write(writer, writer_rx, languageId_clone) {
                    error!("Thread {} exited with error: {:?}", writer_thread_name, err);
                }
            })?;

        Ok(RpcClient {
            languageId,
            id: Arc::new(Mutex::new(0)),
            process_id,
            reader_tx,
            writer_tx,
        })
    }

    pub fn call<R: DeserializeOwned>(
        &self,
        method: impl AsRef<str>,
        params: impl Serialize,
    ) -> Fallible<R> {
        let method = method.as_ref();
        let id = {
            let mut id = self
                .id
                .lock()
                .map_err(|err| format_err!("Failed to lock msg id: {}", err))?;
            *id += 1;
            *id
        };
        let msg = rpc::MethodCall {
            jsonrpc: Some(rpc::Version::V2),
            id: rpc::Id::Num(id),
            method: method.to_owned(),
            params: params.to_params()?,
        };
        let (tx, rx) = bounded(1);
        self.reader_tx.send((id, tx))?;
        self.writer_tx.send(vim::RawMessage::MethodCall(msg))?;
        // TODO: duration from config.
        match rx.recv_timeout(Duration::from_secs(60))? {
            rpc::Output::Success(ok) => Ok(serde_json::from_value(ok.result)?),
            rpc::Output::Failure(err) => bail!("Error: {:?}", err),
        }
    }

    pub fn notify(&self, method: impl AsRef<str>, params: impl Serialize) -> Fallible<()> {
        let method = method.as_ref();

        let msg = rpc::Notification {
            jsonrpc: Some(rpc::Version::V2),
            method: method.to_owned(),
            params: params.to_params()?,
        };
        self.writer_tx.send(vim::RawMessage::Notification(msg))?;
        Ok(())
    }

    pub fn output(&self, id: Id, result: Fallible<impl Serialize>) -> Fallible<()> {
        let output = match result {
            Ok(ok) => rpc::Output::Success(rpc::Success {
                jsonrpc: Some(rpc::Version::V2),
                id: rpc::Id::Num(id),
                result: serde_json::to_value(ok)?,
            }),
            Err(err) => rpc::Output::Failure(rpc::Failure {
                jsonrpc: Some(rpc::Version::V2),
                id: rpc::Id::Num(id),
                error: err.to_rpc_error(),
            }),
        };

        self.writer_tx.send(vim::RawMessage::Output(output))?;
        Ok(())
    }
}

fn loop_read(
    reader: impl BufRead,
    reader_rx: Receiver<(Id, Sender<rpc::Output>)>,
    sink: Sender<Call>,
    languageId: LanguageId,
) -> Fallible<()> {
    let mut pending_outputs = HashMap::new();

    // Count how many consequent empty lines.
    let mut count_empty_lines = 0;

    let mut reader = reader;
    let mut content_length = 0;
    loop {
        let mut message = String::new();
        let mut line = String::new();
        if languageId.is_some() {
            reader.read_line(&mut line)?;
            let line = line.trim();
            if line.is_empty() {
                count_empty_lines += 1;
                if count_empty_lines > 5 {
                    bail!("Unable to read from language server");
                }

                let mut buf = vec![0; content_length];
                reader.read_exact(buf.as_mut_slice())?;
                message = String::from_utf8(buf)?;
            } else {
                count_empty_lines = 0;
                if !line.starts_with("Content-Length") {
                    continue;
                }

                let tokens: Vec<&str> = line.splitn(2, ':').collect();
                let len = tokens
                    .get(1)
                    .ok_or_else(|| format_err!("Failed to get length! tokens: {:?}", tokens))?
                    .trim();
                content_length = usize::from_str(len)?;
            }
        } else if reader.read_line(&mut message)? == 0 {
            break;
        }

        let message = message.trim();
        if message.is_empty() {
            continue;
        }
        info!("<= {:?} {}", languageId, message);
        // FIXME: Remove extra `meta` property from javascript-typescript-langserver.
        let s = message.replace(r#","meta":{}"#, "");
        let message = serde_json::from_str(&s);
        if let Err(ref err) = message {
            error!(
                "Failed to deserialize output: {}\n\n Message: {}\n\nError: {:?}",
                err, s, err
            );
            continue;
        }
        // TODO: cleanup.
        let message = message.unwrap();
        match message {
            vim::RawMessage::MethodCall(method_call) => {
                sink.send(Call::MethodCall(languageId.clone(), method_call))?;
            }
            vim::RawMessage::Notification(notification) => {
                sink.send(Call::Notification(languageId.clone(), notification))?;
            }
            vim::RawMessage::Output(output) => {
                while let Ok((id, tx)) = reader_rx.try_recv() {
                    pending_outputs.insert(id, tx);
                }

                if let Some(tx) = pending_outputs.remove(&output.id().to_int()?) {
                    tx.send(output)
                        .map_err(|output| format_err!("Failed to send output: {:?}", output))?;
                }
            }
        };
    }

    info!("reader-{:?} terminated", languageId);
    Ok(())
}

fn loop_write(
    writer: impl Write,
    rx: Receiver<vim::RawMessage>,
    languageId: LanguageId,
) -> Fallible<()> {
    let mut writer = writer;

    for msg in rx.iter() {
        let s = serde_json::to_string(&msg)?;
        info!("=> {:?} {}", languageId, s);
        if languageId.is_none() {
            // Use different convention for two reasons,
            // 1. If using '\r\ncontent', nvim will receive output as `\r` + `content`, while vim
            // receives `content`.
            // 2. Without last line ending, vim output handler won't be triggered.
            write!(writer, "Content-Length: {}\n\n{}\n", s.len(), s)?;
        } else {
            write!(writer, "Content-Length: {}\r\n\r\n{}", s.len(), s)?;
        };
        writer.flush()?;
    }
    Ok(())
}
<commit_msg>fix: Fix RawMessage enum path<commit_after>use super::*;
use crate::types::{Call, RawMessage};
use crate::vim;
use crossbeam_channel::{bounded, unbounded, Receiver, Sender};

#[derive(Clone, Serialize)]
pub struct RpcClient {
    languageId: LanguageId,
    // TODO: make atomic.
    #[serde(skip_serializing)]
    id: Arc<Mutex<Id>>,
    #[serde(skip_serializing)]
    writer_tx: Sender<RawMessage>,
    #[serde(skip_serializing)]
    reader_tx: Sender<(Id, Sender<rpc::Output>)>,
    pub process_id: Option<u32>,
}

impl RpcClient {
    #[allow(clippy::new_ret_no_self)]
    pub fn new(
        languageId: LanguageId,
        reader: impl BufRead + Send + 'static,
        writer: impl Write + Send + 'static,
        process_id: Option<u32>,
        sink: Sender<Call>,
    ) -> Fallible<Self> {
        let (reader_tx, reader_rx): (Sender<(Id, Sender<rpc::Output>)>, _) = unbounded();

        let languageId_clone = languageId.clone();
        let reader_thread_name = format!("reader-{:?}", languageId);
        thread::Builder::new()
            .name(reader_thread_name.clone())
            .spawn(move || {
                if let Err(err) = loop_read(reader, reader_rx, sink, languageId_clone) {
                    error!("Thread {} exited with error: {:?}", reader_thread_name, err);
                }
            })?;

        let (writer_tx, writer_rx) = unbounded();
        let writer_thread_name = format!("writer-{:?}", languageId);
        let languageId_clone = languageId.clone();
        thread::Builder::new()
            .name(writer_thread_name.clone())
            .spawn(move || {
                if let Err(err) = loop_write(writer, writer_rx, languageId_clone) {
                    error!("Thread {} exited with error: {:?}", writer_thread_name, err);
                }
            })?;

        Ok(RpcClient {
            languageId,
            id: Arc::new(Mutex::new(0)),
            process_id,
            reader_tx,
            writer_tx,
        })
    }

    pub fn call<R: DeserializeOwned>(
        &self,
        method: impl AsRef<str>,
        params: impl Serialize,
    ) -> Fallible<R> {
        let method = method.as_ref();
        let id = {
            let mut id = self
                .id
                .lock()
                .map_err(|err| format_err!("Failed to lock msg id: {}", err))?;
            *id += 1;
            *id
        };
        let msg = rpc::MethodCall {
            jsonrpc: Some(rpc::Version::V2),
            id: rpc::Id::Num(id),
            method: method.to_owned(),
            params: params.to_params()?,
        };
        let (tx, rx) = bounded(1);
        self.reader_tx.send((id, tx))?;
        self.writer_tx.send(RawMessage::MethodCall(msg))?;
        // TODO: duration from config.
        match rx.recv_timeout(Duration::from_secs(60))? {
            rpc::Output::Success(ok) => Ok(serde_json::from_value(ok.result)?),
            rpc::Output::Failure(err) => bail!("Error: {:?}", err),
        }
    }

    pub fn notify(&self, method: impl AsRef<str>, params: impl Serialize) -> Fallible<()> {
        let method = method.as_ref();

        let msg = rpc::Notification {
            jsonrpc: Some(rpc::Version::V2),
            method: method.to_owned(),
            params: params.to_params()?,
        };
        self.writer_tx.send(RawMessage::Notification(msg))?;
        Ok(())
    }

    pub fn output(&self, id: Id, result: Fallible<impl Serialize>) -> Fallible<()> {
        let output = match result {
            Ok(ok) => rpc::Output::Success(rpc::Success {
                jsonrpc: Some(rpc::Version::V2),
                id: rpc::Id::Num(id),
                result: serde_json::to_value(ok)?,
            }),
            Err(err) => rpc::Output::Failure(rpc::Failure {
                jsonrpc: Some(rpc::Version::V2),
                id: rpc::Id::Num(id),
                error: err.to_rpc_error(),
            }),
        };

        self.writer_tx.send(RawMessage::Output(output))?;
        Ok(())
    }
}

fn loop_read(
    reader: impl BufRead,
    reader_rx: Receiver<(Id, Sender<rpc::Output>)>,
    sink: Sender<Call>,
    languageId: LanguageId,
) -> Fallible<()> {
    let mut pending_outputs = HashMap::new();

    // Count how many consequent empty lines.
    let mut count_empty_lines = 0;

    let mut reader = reader;
    let mut content_length = 0;
    loop {
        let mut message = String::new();
        let mut line = String::new();
        if languageId.is_some() {
            reader.read_line(&mut line)?;
            let line = line.trim();
            if line.is_empty() {
                count_empty_lines += 1;
                if count_empty_lines > 5 {
                    bail!("Unable to read from language server");
                }

                let mut buf = vec![0; content_length];
                reader.read_exact(buf.as_mut_slice())?;
                message = String::from_utf8(buf)?;
            } else {
                count_empty_lines = 0;
                if !line.starts_with("Content-Length") {
                    continue;
                }

                let tokens: Vec<&str> = line.splitn(2, ':').collect();
                let len = tokens
                    .get(1)
                    .ok_or_else(|| format_err!("Failed to get length! tokens: {:?}", tokens))?
                    .trim();
                content_length = usize::from_str(len)?;
            }
        } else if reader.read_line(&mut message)? == 0 {
            break;
        }

        let message = message.trim();
        if message.is_empty() {
            continue;
        }
        info!("<= {:?} {}", languageId, message);
        // FIXME: Remove extra `meta` property from javascript-typescript-langserver.
        let s = message.replace(r#","meta":{}"#, "");
        let message = serde_json::from_str(&s);
        if let Err(ref err) = message {
            error!(
                "Failed to deserialize output: {}\n\n Message: {}\n\nError: {:?}",
                err, s, err
            );
            continue;
        }
        // TODO: cleanup.
        let message = message.unwrap();
        match message {
            RawMessage::MethodCall(method_call) => {
                sink.send(Call::MethodCall(languageId.clone(), method_call))?;
            }
            RawMessage::Notification(notification) => {
                sink.send(Call::Notification(languageId.clone(), notification))?;
            }
            RawMessage::Output(output) => {
                while let Ok((id, tx)) = reader_rx.try_recv() {
                    pending_outputs.insert(id, tx);
                }

                if let Some(tx) = pending_outputs.remove(&output.id().to_int()?) {
                    tx.send(output)
                        .map_err(|output| format_err!("Failed to send output: {:?}", output))?;
                }
            }
        };
    }

    info!("reader-{:?} terminated", languageId);
    Ok(())
}

fn loop_write(
    writer: impl Write,
    rx: Receiver<RawMessage>,
    languageId: LanguageId,
) -> Fallible<()> {
    let mut writer = writer;

    for msg in rx.iter() {
        let s = serde_json::to_string(&msg)?;
        info!("=> {:?} {}", languageId, s);
        if languageId.is_none() {
            // Use different convention for two reasons,
            // 1. If using '\r\ncontent', nvim will receive output as `\r` + `content`, while vim
            // receives `content`.
            // 2. Without last line ending, vim output handler won't be triggered.
            write!(writer, "Content-Length: {}\n\n{}\n", s.len(), s)?;
        } else {
            write!(writer, "Content-Length: {}\r\n\r\n{}", s.len(), s)?;
        };
        writer.flush()?;
    }
    Ok(())
}
<|endoftext|>