<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

#[macro_use]
extern crate log;
extern crate osmpbfreader;
extern crate rustc_serialize;
extern crate docopt;
extern crate mimir;
extern crate rs_es;
extern crate chrono;

extern crate mimirsbrunn;
extern crate serde;
extern crate geo;

#[macro_use]
extern crate mdo;

use std::collections::{BTreeSet, BTreeMap};
use mimir::rubber::Rubber;
use std::collections::BTreeMap;
use std::collections::BTreeSet;

pub type AdminsVec = Vec<Rc<mimir::Admin>>;
pub type StreetsVec = Vec<mimir::Street>;
pub type OsmPbfReader = osmpbfreader::OsmPbfReader<std::fs::File>;
pub type StreetWithRelationSet = BTreeSet<osmpbfreader::OsmId>;
pub type AdminSet = BTreeSet<Rc<mimir::Admin>>;
pub type NameAdminMap = BTreeMap<StreetKey, Vec<osmpbfreader::OsmId>>;

use mimirsbrunn::admin_geofinder::AdminGeoFinder;
use std::rc::Rc;
use std::cell::Cell;

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_input: String,
    flag_level: Vec<u32>,
    flag_city_level: u32,
    flag_connection_string: String,
    flag_import_way: bool,
    flag_import_admin: bool,
    flag_dataset: String,
}

static USAGE: &'static str = "
Usage:
    osm2mimir --help
    osm2mimir --input=<file> [--connection-string=<connection-string>] [--import-way] [--import-admin] [--dataset=<dataset>] [--city-level=<level>] --level=<level> ...

Options:
    -h, --help              Show this message.
    -i, --input=<file>      OSM PBF file.
    -l, --level=<level>     Admin levels to keep.
    -C, --city-level=<level>
                            City level to calculate weight, [default: 8]
    -w, --import-way        Import ways
    -a, --import-admin      Import admins
    -c, --connection-string=<connection-string>
                            Elasticsearch parameters, [default: http://localhost:9200/munin]
    -d, --dataset=<dataset>
                            Name of the dataset, [default: fr]

";

#[derive(Debug)]
struct AdminMatcher {
    admin_levels: BTreeSet<u32>,
}
impl AdminMatcher {
    pub fn new(levels: BTreeSet<u32>) -> AdminMatcher {
        AdminMatcher { admin_levels: levels }
    }

    pub fn is_admin(&self, obj: &osmpbfreader::OsmObj) -> bool {
        match *obj {
            osmpbfreader::OsmObj::Relation(ref rel) => {
                rel.tags.get("boundary").map_or(false, |v| v == "administrative") &&
                rel.tags.get("admin_level").map_or(false, |lvl| {
                    self.admin_levels.contains(&lvl.parse::<u32>().unwrap_or(0))
                })
            }
            _ => false,
        }
    }
}

#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub struct StreetKey {
	pub name: String,
	pub admins: BTreeSet<Rc<mimir::Admin>>,
}

fn parse_osm_pbf(path: &str) -> OsmPbfReader {
    let path = std::path::Path::new(&path);
    osmpbfreader::OsmPbfReader::new(std::fs::File::open(&path).unwrap())
}

fn administrative_regions(pbf: &mut OsmPbfReader, levels: BTreeSet<u32>) -> AdminsVec {
    let mut administrative_regions = AdminsVec::new();
    let matcher = AdminMatcher::new(levels);
    info!("reading pbf...");
    let objects = osmpbfreader::get_objs_and_deps(pbf, |o| matcher.is_admin(o)).unwrap();
    info!("reading pbf done.");
    // load administratives regions
    for (_, obj) in &objects {
        if !matcher.is_admin(&obj) {
            continue;
        }
        if let &osmpbfreader::OsmObj::Relation(ref relation) = obj {
            let level = relation.tags
                                .get("admin_level")
                                .and_then(|s| s.parse().ok());
            let level = match level {
                None => {
                    info!("invalid admin_level for relation {}: admin_level {:?}",
                          relation.id,
                          relation.tags.get("admin_level"));
                    continue;
                }
                Some(l) => l,
            };
            // administrative region with name ?
            let name = match relation.tags.get("name") {
                Some(val) => val,
                None => {
                    warn!("adminstrative region without name for relation {}:  admin_level {} \
                           ignored.",
                          relation.id,
                          level);
                    continue;
                }
            };

            // admininstrative region without coordinates
            let coord_centre = relation.refs
                                       .iter()
                                       .find(|rf| rf.role == "admin_centre")
                                       .and_then(|r| {
                                           objects.get(&r.member).and_then(|value| {
                                               match value {
                                                   &osmpbfreader::OsmObj::Node(ref node) => {
                                                       Some(mimir::CoordWrapper(geo::Coordinate {
                                                           x: node.lat,
                                                           y: node.lon,
                                                       }))
                                                   }
                                                   _ => None,
                                               }
                                           })
                                       });
            let (admin_id, insee_id) = match relation.tags.get("ref:INSEE") {
                Some(val) => (format!("admin:fr:{}", val.trim_left_matches('0')), val.trim_left_matches('0')),
                None => (format!("admin:osm:{}", relation.id), ""),
            };
            let zip_code = match relation.tags.get("addr:postcode") {
                Some(val) => &val[..],
                None => "",
            };
            let boundary = mimirsbrunn::boundaries::build_boundary(&relation, &objects);
            let admin = mimir::Admin {
                id: admin_id,
                insee: insee_id.to_string(),
                level: level,
                label: name.to_string(),
                zip_code: zip_code.to_string(),
                // TODO weight value ?
                weight: Cell::new(0),
                coord: coord_centre,
                boundary: boundary,
            };
            administrative_regions.push(Rc::new(admin));
        }
    }
    return administrative_regions;
}

fn make_admin_geofinder(admins: &AdminsVec) -> AdminGeoFinder {
    let mut geofinder = AdminGeoFinder::new();

    for a in admins {
        geofinder.insert(a.clone());
    }
    geofinder
}

fn get_street_admin(admins_geofinder: &AdminGeoFinder,
                    obj_map: &BTreeMap<osmpbfreader::OsmId, osmpbfreader::OsmObj>,
                    way: &osmpbfreader::objects::Way)
                    -> Vec<Rc<mimir::Admin>> {
    // for the moment we consider that the coord of the way is the coord of it's first node
    let coord = way.nodes
                   .iter()
                   .filter_map(|node_id| obj_map.get(&osmpbfreader::OsmId::Node(*node_id)))
                   .filter_map(|node_obj| {
                       if let &osmpbfreader::OsmObj::Node(ref node) = node_obj {
                           Some(geo::Coordinate {
                               x: node.lat,
                               y: node.lon,
                           })
                       } else {
                           None
                       }
                   })
                   .next();
    coord.map_or(vec![], |c| admins_geofinder.get(&c))
}

fn streets(pbf: &mut OsmPbfReader, admins: &AdminsVec, city_level: u32) -> StreetsVec {
    let admins_geofinder = make_admin_geofinder(admins);

    let is_valid_obj = |obj: &osmpbfreader::OsmObj| -> bool {
        match *obj {
            osmpbfreader::OsmObj::Way(ref way) => {
                way.tags.get("highway").map_or(false, |x| !x.is_empty()) &&
                way.tags.get("name").map_or(false, |x| !x.is_empty())
            }
            osmpbfreader::OsmObj::Relation(ref rel) => {
                rel.tags.get("type").map_or(false, |v| v == "associatedStreet")
            }
            _ => false,
        }
    };
    info!("reading pbf...");
    let objs_map = osmpbfreader::get_objs_and_deps(pbf, is_valid_obj).unwrap();
	info!("reading pbf done.");
    let mut street_rel : StreetWithRelationSet = BTreeSet::new();
    let mut street_list: StreetsVec = vec![];
    // Sometimes, streets can be devided into several "way"s that still have the same street name.
    // The reason why a street is devided may be that a part of the street become a bridge/tunne/etc.
    // In this case, a "relation" tagged with (type = associatedStreet) is used to group all these "way"s.
    // In order not to have duplicates in autocompleion, we should keep only one "way" in the relation

    for (_, rel_obj) in &objs_map {
        if let &osmpbfreader::OsmObj::Relation(ref rel) = rel_obj {
            //TODO : create a street for the first memeber way of the relation but not for the rest.

            for ref_obj in &rel.refs {

                use mdo::option::*;
   	    		let objs_map = &objs_map;
   	    		let street_list = &mut street_list;
   	    		let admins_geofinder = &admins_geofinder;

                mdo! {
                    when ref_obj.member.is_way();
                    obj =<< objs_map.get(&ref_obj.member);
                    let way = match obj {
                        &osmpbfreader::OsmObj::Way(ref w) => w,
                        _ => unreachable!()
                    };
                    way_name =<< way.tags.get("name");
                    let admin = get_street_admin(admins_geofinder, objs_map, way);
                    ret ret(street_list.push(mimir::Street {
							id: way.id.to_string(),
							street_name: way_name.to_string(),
                    		label: way_name.to_string(),
                    		weight: 1,
                    		administrative_regions: admin,
            			}))
                };
                break;
            }

            //Add osmid of all the relation members in de set street_rel.
            //We don't create any street for all the osmid present in street_rel
            for ref_obj in &rel.refs {
                if let &osmpbfreader::OsmId::Way(_) = &ref_obj.member {
                    street_rel.insert(ref_obj.member.clone());
                }
            }
        };
    }

    // we merge all the ways with a key = way_name + admin list of level(=city_level)
    //we use a map NameAdminMap <key, value> to manage the merging of ways
    let mut name_admin_map : NameAdminMap = BTreeMap::new();
    for (osmid, obj) in &objs_map {
        if street_rel.contains(osmid) {
        	continue;
        }
        if let &osmpbfreader::OsmObj::Way(ref way) = obj {
            let admin: BTreeSet<Rc<mimir::Admin>> = get_street_admin(&admins_geofinder, &objs_map, way).into_iter().filter(|admin| admin.level == city_level).collect();
             if let Some(way_name) = way.tags.get("name") {
                 name_admin_map.entry(StreetKey{name: way_name.to_string(), admins: admin}).or_insert(vec![]).push(*osmid)
             }
        }
    }

   	//Create a street for each way with osmid present in in objs_map
   	for (_, way_ids) in name_admin_map {
   	    use mdo::option::*;
   	    let objs_map = &objs_map;
   	    let street_list = &mut street_list;
   	    let admins_geofinder = &admins_geofinder;
   	    mdo! {
			obj =<< objs_map.get(&way_ids[0]);
			way =<< obj.way();
   	        //way =<< way(obj);
   	        way_name =<< way.tags.get("name");
   	        let admins = get_street_admin(admins_geofinder, objs_map, way);
   	        ret ret(street_list.push(mimir::Street{
					id: way.id.to_string(),
					street_name: way_name.to_string(),
                	label: way_name.to_string(),
                	weight: 1,
                	administrative_regions: admins,
   	    		}))
   	    };
   	}

   	street_list
}

fn main() {
    mimir::logger_init().unwrap();
    let args: Args = docopt::Docopt::new(USAGE)
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| e.exit());

    let levels = args.flag_level.iter().cloned().collect();
    let city_level = args.flag_city_level;
    let mut parsed_pbf = parse_osm_pbf(&args.flag_input);
    debug!("creation of indexes");
    let mut rubber = Rubber::new(&args.flag_connection_string);

    info!("creating adminstrative regions");
    let admins = administrative_regions(&mut parsed_pbf, levels);

    let mut streets = streets(&mut parsed_pbf, &admins, city_level);

    for st in &mut streets {
    	for admin in &mut st.administrative_regions {
    		if admin.level == city_level {
    			admin.weight.set(admin.weight.get() + 1)
    		}
    	}
    }

    for st in &mut streets {
    	for admin in &mut st.administrative_regions {
    		if admin.level == city_level {
    			st.weight = admin.weight.get();
    			break;
    		}
    	}
    }

    if args.flag_import_way {
        info!("importing streets into Mimir");
        let nb_streets = rubber.index("way",
                                      &args.flag_dataset,
                                      streets.into_iter())
                               .unwrap();
        info!("Nb of indexed street: {}", nb_streets);
    }

    let nb_admins = rubber.index("admin", &args.flag_dataset, admins.iter())
                          .unwrap();
    info!("Nb of indexed admin: {}", nb_admins);

}
<commit_msg>mimir: some corrections<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

#[macro_use]
extern crate log;
extern crate osmpbfreader;
extern crate rustc_serialize;
extern crate docopt;
extern crate mimir;
extern crate rs_es;
extern crate chrono;

extern crate mimirsbrunn;
extern crate serde;
extern crate geo;

#[macro_use]
extern crate mdo;

use std::collections::{BTreeSet, BTreeMap};
use mimir::rubber::Rubber;
use std::collections::BTreeMap;
use std::collections::BTreeSet;

pub type AdminsVec = Vec<Rc<mimir::Admin>>;
pub type StreetsVec = Vec<mimir::Street>;
pub type OsmPbfReader = osmpbfreader::OsmPbfReader<std::fs::File>;
pub type StreetWithRelationSet = BTreeSet<osmpbfreader::OsmId>;
pub type AdminSet = BTreeSet<Rc<mimir::Admin>>;
pub type NameAdminMap = BTreeMap<StreetKey, Vec<osmpbfreader::OsmId>>;

use mimirsbrunn::admin_geofinder::AdminGeoFinder;
use std::rc::Rc;
use std::cell::Cell;

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_input: String,
    flag_level: Vec<u32>,
    flag_city_level: u32,
    flag_connection_string: String,
    flag_import_way: bool,
    flag_import_admin: bool,
    flag_dataset: String,
}

static USAGE: &'static str = "
Usage:
    osm2mimir --help
    osm2mimir --input=<file> [--connection-string=<connection-string>] [--import-way] [--import-admin] [--dataset=<dataset>] [--city-level=<level>] --level=<level> ...

Options:
    -h, --help              Show this message.
    -i, --input=<file>      OSM PBF file.
    -l, --level=<level>     Admin levels to keep.
    -C, --city-level=<level>
                            City level to calculate weight, [default: 8]
    -w, --import-way        Import ways
    -a, --import-admin      Import admins
    -c, --connection-string=<connection-string>
                            Elasticsearch parameters, [default: http://localhost:9200/munin]
    -d, --dataset=<dataset>
                            Name of the dataset, [default: fr]

";

#[derive(Debug)]
struct AdminMatcher {
    admin_levels: BTreeSet<u32>,
}
impl AdminMatcher {
    pub fn new(levels: BTreeSet<u32>) -> AdminMatcher {
        AdminMatcher { admin_levels: levels }
    }

    pub fn is_admin(&self, obj: &osmpbfreader::OsmObj) -> bool {
        match *obj {
            osmpbfreader::OsmObj::Relation(ref rel) => {
                rel.tags.get("boundary").map_or(false, |v| v == "administrative") &&
                rel.tags.get("admin_level").map_or(false, |lvl| {
                    self.admin_levels.contains(&lvl.parse::<u32>().unwrap_or(0))
                })
            }
            _ => false,
        }
    }
}

#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub struct StreetKey {
	pub name: String,
	pub admins: AdminSet,
}

fn parse_osm_pbf(path: &str) -> OsmPbfReader {
    let path = std::path::Path::new(&path);
    osmpbfreader::OsmPbfReader::new(std::fs::File::open(&path).unwrap())
}

fn administrative_regions(pbf: &mut OsmPbfReader, levels: BTreeSet<u32>) -> AdminsVec {
    let mut administrative_regions = AdminsVec::new();
    let matcher = AdminMatcher::new(levels);
    info!("reading pbf...");
    let objects = osmpbfreader::get_objs_and_deps(pbf, |o| matcher.is_admin(o)).unwrap();
    info!("reading pbf done.");
    // load administratives regions
    for (_, obj) in &objects {
        if !matcher.is_admin(&obj) {
            continue;
        }
        if let &osmpbfreader::OsmObj::Relation(ref relation) = obj {
            let level = relation.tags
                                .get("admin_level")
                                .and_then(|s| s.parse().ok());
            let level = match level {
                None => {
                    info!("invalid admin_level for relation {}: admin_level {:?}",
                          relation.id,
                          relation.tags.get("admin_level"));
                    continue;
                }
                Some(l) => l,
            };
            // administrative region with name ?
            let name = match relation.tags.get("name") {
                Some(val) => val,
                None => {
                    warn!("adminstrative region without name for relation {}:  admin_level {} \
                           ignored.",
                          relation.id,
                          level);
                    continue;
                }
            };

            // admininstrative region without coordinates
            let coord_centre = relation.refs
                                       .iter()
                                       .find(|rf| rf.role == "admin_centre")
                                       .and_then(|r| {
                                           objects.get(&r.member).and_then(|value| {
                                               match value {
                                                   &osmpbfreader::OsmObj::Node(ref node) => {
                                                       Some(mimir::CoordWrapper(geo::Coordinate {
                                                           x: node.lat,
                                                           y: node.lon,
                                                       }))
                                                   }
                                                   _ => None,
                                               }
                                           })
                                       });
            let (admin_id, insee_id) = match relation.tags.get("ref:INSEE") {
                Some(val) => (format!("admin:fr:{}", val.trim_left_matches('0')), val.trim_left_matches('0')),
                None => (format!("admin:osm:{}", relation.id), ""),
            };
            let zip_code = match relation.tags.get("addr:postcode") {
                Some(val) => &val[..],
                None => "",
            };
            let boundary = mimirsbrunn::boundaries::build_boundary(&relation, &objects);
            let admin = mimir::Admin {
                id: admin_id,
                insee: insee_id.to_string(),
                level: level,
                label: name.to_string(),
                zip_code: zip_code.to_string(),
                // TODO weight value ?
                weight: Cell::new(0),
                coord: coord_centre,
                boundary: boundary,
            };
            administrative_regions.push(Rc::new(admin));
        }
    }
    return administrative_regions;
}

fn make_admin_geofinder(admins: &AdminsVec) -> AdminGeoFinder {
    let mut geofinder = AdminGeoFinder::new();

    for a in admins {
        geofinder.insert(a.clone());
    }
    geofinder
}

fn get_street_admin(admins_geofinder: &AdminGeoFinder,
                    obj_map: &BTreeMap<osmpbfreader::OsmId, osmpbfreader::OsmObj>,
                    way: &osmpbfreader::objects::Way)
                    -> Vec<Rc<mimir::Admin>> {
    // for the moment we consider that the coord of the way is the coord of it's first node
    let coord = way.nodes
                   .iter()
                   .filter_map(|node_id| obj_map.get(&osmpbfreader::OsmId::Node(*node_id)))
                   .filter_map(|node_obj| {
                       if let &osmpbfreader::OsmObj::Node(ref node) = node_obj {
                           Some(geo::Coordinate {
                               x: node.lat,
                               y: node.lon,
                           })
                       } else {
                           None
                       }
                   })
                   .next();
    coord.map_or(vec![], |c| admins_geofinder.get(&c))
}

fn streets(pbf: &mut OsmPbfReader, admins: &AdminsVec, city_level: u32) -> StreetsVec {
    let admins_geofinder = make_admin_geofinder(admins);

    let is_valid_obj = |obj: &osmpbfreader::OsmObj| -> bool {
        match *obj {
            osmpbfreader::OsmObj::Way(ref way) => {
                way.tags.get("highway").map_or(false, |x| !x.is_empty()) &&
                way.tags.get("name").map_or(false, |x| !x.is_empty())
            }
            osmpbfreader::OsmObj::Relation(ref rel) => {
                rel.tags.get("type").map_or(false, |v| v == "associatedStreet")
            }
            _ => false,
        }
    };
    info!("reading pbf...");
    let objs_map = osmpbfreader::get_objs_and_deps(pbf, is_valid_obj).unwrap();
	info!("reading pbf done.");
    let mut street_rel : StreetWithRelationSet = BTreeSet::new();
    let mut street_list: StreetsVec = vec![];
    // Sometimes, streets can be devided into several "way"s that still have the same street name.
    // The reason why a street is devided may be that a part of the street become a bridge/tunne/etc.
    // In this case, a "relation" tagged with (type = associatedStreet) is used to group all these "way"s.
    // In order not to have duplicates in autocompleion, we should tag the osm ways in the relation not to index them twice.

    for (_, rel_obj) in &objs_map {
        if let &osmpbfreader::OsmObj::Relation(ref rel) = rel_obj {
            let way_name = rel.tags.get("name");
            for ref_obj in &rel.refs {

                use mdo::option::*;
   	    		let objs_map = &objs_map;
   	    		let street_list = &mut street_list;
   	    		let admins_geofinder = &admins_geofinder;

                let inserted = mdo! {
                    when ref_obj.member.is_way();
                    when ref_obj.role == "street";
                    obj =<< objs_map.get(&ref_obj.member);
                    let way = match obj {
                        &osmpbfreader::OsmObj::Way(ref w) => w,
                        _ => unreachable!()
                    };
                    way_name =<< way_name.or_else(|| way.tags.get("name"));
                    let admin = get_street_admin(admins_geofinder, objs_map, way);
                    ret ret(street_list.push(mimir::Street {
							id: way.id.to_string(),
							street_name: way_name.to_string(),
                    		label: way_name.to_string(),
                    		weight: 1,
                    		administrative_regions: admin,
            			}))
                };
                if inserted.is_some() {
                	break;
                }
            }

            //Add osmid of all the relation members in de set
            //We don't create any street for all the osmid present in street_rel
            for ref_obj in &rel.refs {
                if ref_obj.member.is_way() {
                    street_rel.insert(ref_obj.member);
                }
            }
        };
    }

    // we merge all the ways with a key = way_name + admin list of level(=city_level)
    //we use a map NameAdminMap <key, value> to manage the merging of ways
    let mut name_admin_map : NameAdminMap = BTreeMap::new();
    for (osmid, obj) in &objs_map {
        if street_rel.contains(osmid) {
        	continue;
        }
        use mdo::option::*;
        let admins_geofinder = &admins_geofinder;
        let objs_map = &objs_map;
        let name_admin_map = &mut name_admin_map;
        mdo! {
            way =<< obj.way();
            let admins: BTreeSet<Rc<mimir::Admin>> = get_street_admin(admins_geofinder, objs_map, way)
            	.into_iter()
            	.filter(|admin| admin.level == city_level)
            	.collect();

            way_name =<< way.tags.get("name");
            let key = StreetKey{name: way_name.to_string(), admins: admins};
            ret ret(name_admin_map.entry(key).or_insert(vec![]).push(*osmid))
        };
    }

   	//Create a street for each way with osmid present in in objs_map
   	for (_, way_ids) in name_admin_map {
		use mdo::option::*;
		let objs_map = &objs_map;
		let street_list = &mut street_list;
		let admins_geofinder = &admins_geofinder;
   	    mdo! {
			obj =<< objs_map.get(&way_ids[0]);
			way =<< obj.way();
   	        way_name =<< way.tags.get("name");
   	        let admins = get_street_admin(admins_geofinder, objs_map, way);
   	        ret ret(street_list.push(mimir::Street{
				id: way.id.to_string(),
				street_name: way_name.to_string(),
				label: way_name.to_string(),
                weight: 1,
                administrative_regions: admins,
   	        }))
   	    };
   	}

   	street_list
}

fn main() {
    mimir::logger_init().unwrap();
    let args: Args = docopt::Docopt::new(USAGE)
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| e.exit());

    let levels = args.flag_level.iter().cloned().collect();
    let city_level = args.flag_city_level;
    let mut parsed_pbf = parse_osm_pbf(&args.flag_input);
    debug!("creation of indexes");
    let mut rubber = Rubber::new(&args.flag_connection_string);

    info!("creating adminstrative regions");
    let admins = administrative_regions(&mut parsed_pbf, levels);

    let mut streets = streets(&mut parsed_pbf, &admins, city_level);

    for st in &mut streets {
    	for admin in &mut st.administrative_regions {
    		if admin.level == city_level {
    			admin.weight.set(admin.weight.get() + 1)
    		}
    	}
    }

    for st in &mut streets {
    	for admin in &mut st.administrative_regions {
    		if admin.level == city_level {
    			st.weight = admin.weight.get();
    			break;
    		}
    	}
    }

    if args.flag_import_way {
        info!("importing streets into Mimir");
        let nb_streets = rubber.index("way",
                                      &args.flag_dataset,
                                      streets.into_iter())
                               .unwrap();
        info!("Nb of indexed street: {}", nb_streets);
    }

    let nb_admins = rubber.index("admin", &args.flag_dataset, admins.iter())
                          .unwrap();
    info!("Nb of indexed admin: {}", nb_admins);

}
<|endoftext|>


<commit_before>// This file is part of Genesis.

// Genesis is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Genesis is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with Genesis.  If not, see <http://www.gnu.org/licenses/>.
#![allow(dead_code)]

use core::prelude::*;
use super::ioport;

static PORT_BASE: u16 = 0x3F8;
// when DLAB = 0
static DATA_REG: u16 = 0;
static INT_ENABLE: u16 = 1;

// when DLAB = 1
static BAUD_DIV_LSB: u16 = 0;
static BAUD_DIV_MSB: u16 = 1;

static LINE_CTRL_REG: u16 = 3;
static LINE_CTRL_REG_CHARLEN8: u8 = 1 << 0 | 1 << 1;
static LINE_CTRL_REG_DLAB: u8 = 1 << 7;

static LINE_STATUS_REG: u16 = 5;
static LINE_STATUS_REG_THR_EMPTY: u8 = 1 << 5;

pub unsafe fn init() {
    ioport::out(PORT_BASE + INT_ENABLE, 0u8); // disable interrupts

    ioport::out(PORT_BASE + LINE_CTRL_REG, LINE_CTRL_REG_DLAB); // enable dlab
    // XXX: hard coded 115200 baud
    ioport::out(PORT_BASE + BAUD_DIV_LSB, 1u8);
    ioport::out(PORT_BASE + BAUD_DIV_MSB, 0u8);

    // XXX: hard coded as 8N1 (8 bits, no parity, one stop bit)
    ioport::out(PORT_BASE + LINE_CTRL_REG, LINE_CTRL_REG_CHARLEN8);
}

unsafe fn is_transmit_empty() -> bool {
    ioport::inb(PORT_BASE + LINE_STATUS_REG) & LINE_STATUS_REG_THR_EMPTY != 0
}

unsafe fn putc(c: u8) {
    while !is_transmit_empty() {}

    ioport::out(PORT_BASE + DATA_REG, c);
}

pub unsafe fn write_str(s: &str) {
    for c in s.bytes() {
        putc(c);
    }
}
<commit_msg>serial: Use const for constants<commit_after>// This file is part of Genesis.

// Genesis is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Genesis is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with Genesis.  If not, see <http://www.gnu.org/licenses/>.
#![allow(dead_code)]

use core::prelude::*;
use super::ioport;

const PORT_BASE: u16 = 0x3F8;
// when DLAB = 0
const DATA_REG: u16 = 0;
const INT_ENABLE: u16 = 1;

// when DLAB = 1
const BAUD_DIV_LSB: u16 = 0;
const BAUD_DIV_MSB: u16 = 1;

const LINE_CTRL_REG: u16 = 3;
const LINE_CTRL_REG_CHARLEN8: u8 = 1 << 0 | 1 << 1;
const LINE_CTRL_REG_DLAB: u8 = 1 << 7;

const LINE_STATUS_REG: u16 = 5;
const LINE_STATUS_REG_THR_EMPTY: u8 = 1 << 5;

pub unsafe fn init() {
    ioport::out(PORT_BASE + INT_ENABLE, 0u8); // disable interrupts

    ioport::out(PORT_BASE + LINE_CTRL_REG, LINE_CTRL_REG_DLAB); // enable dlab
    // XXX: hard coded 115200 baud
    ioport::out(PORT_BASE + BAUD_DIV_LSB, 1u8);
    ioport::out(PORT_BASE + BAUD_DIV_MSB, 0u8);

    // XXX: hard coded as 8N1 (8 bits, no parity, one stop bit)
    ioport::out(PORT_BASE + LINE_CTRL_REG, LINE_CTRL_REG_CHARLEN8);
}

unsafe fn is_transmit_empty() -> bool {
    ioport::inb(PORT_BASE + LINE_STATUS_REG) & LINE_STATUS_REG_THR_EMPTY != 0
}

unsafe fn putc(c: u8) {
    while !is_transmit_empty() {}

    ioport::out(PORT_BASE + DATA_REG, c);
}

pub unsafe fn write_str(s: &str) {
    for c in s.bytes() {
        putc(c);
    }
}
<|endoftext|>


<commit_before>extern crate structopt;

mod calculate;
mod exceptions;
mod measure;

use crate::calculate::Calculation;
use crate::exceptions::CalculateError;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use structopt::StructOpt;

// This type defines the commandline interface and is generated
// by `derive(StructOpt)`
#[derive(Clone, Debug, StructOpt)]
#[structopt(name = "performance", about = "performance regression testing runner")]
enum Opt {
    #[structopt(name = "measure")]
    Measure {
        #[structopt(parse(from_os_str))]
        #[structopt(short)]
        projects_dir: PathBuf,
        #[structopt(short)]
        branch_name: String,
    },
    #[structopt(name = "calculate")]
    Calculate {
        #[structopt(parse(from_os_str))]
        #[structopt(short)]
        results_dir: PathBuf,
    },
}

// enables proper useage of exit() in main.
// https://doc.rust-lang.org/std/process/fn.exit.html#examples
//
// This is where all the printing should happen. Exiting happens
// in main, and module functions should only return values.
fn run_app() -> Result<i32, CalculateError> {
    // match what the user inputs from the cli
    match Opt::from_args() {
        // measure subcommand
        Opt::Measure {
            projects_dir,
            branch_name,
        } => {
            // if there are any nonzero exit codes from the hyperfine runs,
            // return the first one. otherwise return zero.
            measure::measure(&projects_dir, &branch_name)
                .or_else(|e| Err(CalculateError::CalculateIOError(e)))?
                .iter()
                .map(|status| status.code())
                .flatten()
                .filter(|code| *code != 0)
                .collect::<Vec<i32>>()
                .get(0)
                .map_or(Ok(0), |x| {
                    println!("Main: a child process exited with a nonzero status code.");
                    Ok(*x)
                })
        }

        // calculate subcommand
        Opt::Calculate { results_dir } => {
            // get all the calculations or gracefully show the user an exception
            let calculations = calculate::regressions(&results_dir)?;

            // print all calculations to stdout so they can be easily debugged
            // via CI.
            println!(":: All Calculations ::\n");
            for c in &calculations {
                println!("{:#?}\n", c);
            }
            println!("");

            // indented json string representation of the calculations array
            let json_calcs = serde_json::to_string_pretty(&calculations)
                .expect("Main: Failed to serialize calculations to json");

            // create the empty destination file, and write the json string
            let outfile = &mut results_dir.into_os_string();
            outfile.push("/final_calculations.json");
            let mut f = File::create(outfile).expect("Main: Unable to create file");
            f.write_all(json_calcs.as_bytes())
                .expect("Main: Unable to write data");

            // filter for regressions
            let regressions: Vec<&Calculation> =
                calculations.iter().filter(|c| c.regression).collect();

            // return a non-zero exit code if there are regressions
            match regressions[..] {
                [] => {
                    println!("congrats! no regressions :)");
                    Ok(0)
                }
                _ => {
                    // print all calculations to stdout so they can be easily
                    // debugged via CI.
                    println!(":: Regressions Found ::\n");
                    println!("");
                    for r in regressions {
                        println!("{:#?}\n", r);
                    }
                    println!("");
                    Ok(1)
                }
            }
        }
    }
}

fn main() {
    std::process::exit(match run_app() {
        Ok(code) => code,
        Err(err) => {
            eprintln!("{}", err);
            1
        }
    });
}
<commit_msg>remove unnecessary newline printing<commit_after>extern crate structopt;

mod calculate;
mod exceptions;
mod measure;

use crate::calculate::Calculation;
use crate::exceptions::CalculateError;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use structopt::StructOpt;

// This type defines the commandline interface and is generated
// by `derive(StructOpt)`
#[derive(Clone, Debug, StructOpt)]
#[structopt(name = "performance", about = "performance regression testing runner")]
enum Opt {
    #[structopt(name = "measure")]
    Measure {
        #[structopt(parse(from_os_str))]
        #[structopt(short)]
        projects_dir: PathBuf,
        #[structopt(short)]
        branch_name: String,
    },
    #[structopt(name = "calculate")]
    Calculate {
        #[structopt(parse(from_os_str))]
        #[structopt(short)]
        results_dir: PathBuf,
    },
}

// enables proper useage of exit() in main.
// https://doc.rust-lang.org/std/process/fn.exit.html#examples
//
// This is where all the printing should happen. Exiting happens
// in main, and module functions should only return values.
fn run_app() -> Result<i32, CalculateError> {
    // match what the user inputs from the cli
    match Opt::from_args() {
        // measure subcommand
        Opt::Measure {
            projects_dir,
            branch_name,
        } => {
            // if there are any nonzero exit codes from the hyperfine runs,
            // return the first one. otherwise return zero.
            measure::measure(&projects_dir, &branch_name)
                .or_else(|e| Err(CalculateError::CalculateIOError(e)))?
                .iter()
                .map(|status| status.code())
                .flatten()
                .filter(|code| *code != 0)
                .collect::<Vec<i32>>()
                .get(0)
                .map_or(Ok(0), |x| {
                    println!("Main: a child process exited with a nonzero status code.");
                    Ok(*x)
                })
        }

        // calculate subcommand
        Opt::Calculate { results_dir } => {
            // get all the calculations or gracefully show the user an exception
            let calculations = calculate::regressions(&results_dir)?;

            // print all calculations to stdout so they can be easily debugged
            // via CI.
            println!(":: All Calculations ::\n");
            for c in &calculations {
                println!("{:#?}\n", c);
            }

            // indented json string representation of the calculations array
            let json_calcs = serde_json::to_string_pretty(&calculations)
                .expect("Main: Failed to serialize calculations to json");

            // create the empty destination file, and write the json string
            let outfile = &mut results_dir.into_os_string();
            outfile.push("/final_calculations.json");
            let mut f = File::create(outfile).expect("Main: Unable to create file");
            f.write_all(json_calcs.as_bytes())
                .expect("Main: Unable to write data");

            // filter for regressions
            let regressions: Vec<&Calculation> =
                calculations.iter().filter(|c| c.regression).collect();

            // return a non-zero exit code if there are regressions
            match regressions[..] {
                [] => {
                    println!("congrats! no regressions :)");
                    Ok(0)
                }
                _ => {
                    // print all calculations to stdout so they can be easily
                    // debugged via CI.
                    println!(":: Regressions Found ::\n");
                    for r in regressions {
                        println!("{:#?}\n", r);
                    }
                    Ok(1)
                }
            }
        }
    }
}

fn main() {
    std::process::exit(match run_app() {
        Ok(code) => code,
        Err(err) => {
            eprintln!("{}", err);
            1
        }
    });
}
<|endoftext|>


<commit_before>use cocoa::base::id;

pub trait MTLCommandBuffer {

}

impl MTLCommandBuffer for id {

}
<commit_msg>Add MTLCommandBuffer::renderCommandEncoderWithDescriptor to MTLCommandBuffer trait def<commit_after>use cocoa::base::id;

pub trait MTLCommandBuffer {
    fn renderCommandEncoderWithDescriptor(self, renderPassDescriptor: id) -> id;
}

impl MTLCommandBuffer for id {

}
<|endoftext|>


<commit_before>use clap::{SubCommand, App, Arg, ArgMatches};
use log::{LogRecord, LogLevel, SetLoggerError};
use env_logger::LogBuilder;
use colored::*;

use std::path::Path;
use std::marker::PhantomData;
use std::fs;
use std::env;
use std::time::{SystemTime, UNIX_EPOCH};

use exonum::config::ConfigFile;
use exonum::blockchain::GenesisConfig;
use exonum::node::NodeConfig;
use exonum::crypto::gen_keypair;
use exonum::storage::Storage;

pub struct GenerateCommand<'a, 'b>
    where 'a: 'b
{
    _p: PhantomData<App<'a, 'b>>,
}

// TODO avoid unwraps here, implement Error chain

impl<'a, 'b> GenerateCommand<'a, 'b>
    where 'a: 'b
{
    pub fn new() -> App<'a, 'b> {
        SubCommand::with_name("generate")
            .about("Generates genesis configuration")
            .arg(Arg::with_name("OUTPUT_DIR")
                     .short("o")
                     .long("output-dir")
                     .value_name("OUTPUT_DIR")
                     .required(true)
                     .takes_value(true))
            .arg(Arg::with_name("START_PORT")
                     .short("p")
                     .long("start-port")
                     .value_name("START_PORT")
                     .required(false)
                     .takes_value(true))
            .arg(Arg::with_name("COUNT")
                     .help("Validators count")
                     .required(true)
                     .index(1))
    }

    pub fn output_dir(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("OUTPUT_DIR").unwrap())
    }

    pub fn validators_count(matches: &'a ArgMatches<'a>) -> u8 {
        matches.value_of("COUNT").unwrap().parse().unwrap()
    }

    pub fn start_port(matches: &'a ArgMatches<'a>) -> Option<u16> {
        matches
            .value_of("START_PORT")
            .map(|p| p.parse().unwrap())
    }

    pub fn execute(matches: &'a ArgMatches<'a>) {
        let dir = Self::output_dir(matches);
        let count = Self::validators_count(matches);
        let start_port = Self::start_port(matches).unwrap_or_else(|| 2000);

        let dir = dir.join("validators");
        if !dir.exists() {
            fs::create_dir_all(&dir).unwrap();
        }

        let configs = generate_testnet_config(count, start_port);
        for (idx, cfg) in configs.into_iter().enumerate() {
            let file_name = format!("{}.toml", idx);
            ConfigFile::save(&cfg, &dir.join(file_name)).unwrap();
        }
    }
}

pub struct RunCommand<'a, 'b>
    where 'a: 'b
{
    _p: PhantomData<App<'a, 'b>>,
}

impl<'a, 'b> RunCommand<'a, 'b>
    where 'a: 'b
{
    pub fn new() -> App<'a, 'b> {
        SubCommand::with_name("run")
            .arg(Arg::with_name("NODE_CONFIG_PATH")
                     .short("c")
                     .long("node-config")
                     .value_name("NODE_CONFIG_PATH")
                     .help("Path to node configuration file")
                     .required(true)
                     .takes_value(true))
            .arg(Arg::with_name("LEVELDB_PATH")
                     .short("d")
                     .long("leveldb-path")
                     .value_name("LEVELDB_PATH")
                     .help("Use leveldb database with the given path")
                     .required(false)
                     .takes_value(true))
    }

    pub fn node_config_path(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("NODE_CONFIG_PATH").unwrap())
    }

    pub fn node_config(matches: &'a ArgMatches<'a>) -> NodeConfig {
        let path = Self::node_config_path(matches);
        ConfigFile::load(path).unwrap()
    }

    pub fn leveldb_path(matches: &'a ArgMatches<'a>) -> Option<&'a Path> {
        matches.value_of("LEVELDB_PATH").map(Path::new)
    }

    #[cfg(not(feature="memorydb"))]
    pub fn db(matches: &'a ArgMatches<'a>) -> Storage {
        use exonum::storage::{LevelDB, LevelDBOptions};

        let path = Self::leveldb_path(matches).unwrap();
        let mut options = LevelDBOptions::new();
        options.create_if_missing = true;
        LevelDB::new(path, options).unwrap()
    }

    #[cfg(feature="memorydb")]
    pub fn db(_: &'a ArgMatches<'a>) -> Storage {
        use exonum::storage::MemoryDB;
        MemoryDB::new()
    }
}

fn has_colors() -> bool {
    use term::terminfo::TerminfoTerminal;
    use term::Terminal;
    use std::io;

    let out = io::stderr();
    if let Some(term) = TerminfoTerminal::new(out) {
        term.supports_color()
    } else {
        false
    }
}

pub fn init_logger() -> Result<(), SetLoggerError> {
    let format = |record: &LogRecord| {
        let ts = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
        let secs = ts.as_secs().to_string();
        let millis = (ts.subsec_nanos() as u64 / 1000000).to_string();

        let module = record.location().module_path();
        let file = record.location().file();
        let line = record.location().line();

        let source_path;
        let verbose_src_path;
        if env::var("EXONUM_SRC_PATH").is_ok() {
            let param_parse = env::var("EXONUM_SRC_PATH").unwrap().parse::<bool>();
            if let Ok(flag) = param_parse {
                verbose_src_path = flag;
            } else {
                verbose_src_path = false;
            }
        } else {
            verbose_src_path = false;
        }

        if verbose_src_path {
            source_path = format!("{}:{}:{}", module, file, line);
        } else {
            source_path = format!("{}", module);
        }

        if has_colors() {
            let level = match record.level() {
                LogLevel::Error => "ERROR".red(),
                LogLevel::Warn => "WARN".yellow(),
                LogLevel::Info => "INFO".green(),
                LogLevel::Debug => "DEBUG".cyan(),
                LogLevel::Trace => "TRACE".white(),
            };
            format!("[{} : {}] - [ {} ] - {} - {}",
                    secs.bold(),
                    millis.bold(),
                    level,
                    &source_path,
                    record.args())
        } else {
            let level = match record.level() {
                LogLevel::Error => "ERROR",
                LogLevel::Warn => "WARN",
                LogLevel::Info => "INFO",
                LogLevel::Debug => "DEBUG",
                LogLevel::Trace => "TRACE",
            };
            format!("[{} : {}] - [ {} ] - {} - {}",
                    secs,
                    millis,
                    level,
                    &source_path,
                    record.args())
        }
    };

    let mut builder = LogBuilder::new();
    builder.format(format);

    if env::var("RUST_LOG").is_ok() {
        builder.parse(&env::var("RUST_LOG").unwrap());
    }

    builder.init()
}

pub fn generate_testnet_config(count: u8, start_port: u16) -> Vec<NodeConfig> {
    let validators = (0..count as usize)
        .map(|_| gen_keypair())
        .collect::<Vec<_>>();
    let genesis = GenesisConfig::new(validators.iter().map(|x| x.0));
    let peers = (0..validators.len())
        .map(|x| {
                 format!("127.0.0.1:{}", start_port + x as u16)
                     .parse()
                     .unwrap()
             })
        .collect::<Vec<_>>();

    validators
        .into_iter()
        .enumerate()
        .map(|(idx, validator)| {
            NodeConfig {
                listen_address: peers[idx],
                network: Default::default(),
                peers: peers.clone(),
                public_key: validator.0,
                secret_key: validator.1,
                genesis: genesis.clone(),
            }
        })
        .collect::<Vec<_>>()
}
<commit_msg>renamed env variable for verbose logging of logging location:file, line<commit_after>use clap::{SubCommand, App, Arg, ArgMatches};
use log::{LogRecord, LogLevel, SetLoggerError};
use env_logger::LogBuilder;
use colored::*;

use std::path::Path;
use std::marker::PhantomData;
use std::fs;
use std::env;
use std::time::{SystemTime, UNIX_EPOCH};

use exonum::config::ConfigFile;
use exonum::blockchain::GenesisConfig;
use exonum::node::NodeConfig;
use exonum::crypto::gen_keypair;
use exonum::storage::Storage;

pub struct GenerateCommand<'a, 'b>
    where 'a: 'b
{
    _p: PhantomData<App<'a, 'b>>,
}

// TODO avoid unwraps here, implement Error chain

impl<'a, 'b> GenerateCommand<'a, 'b>
    where 'a: 'b
{
    pub fn new() -> App<'a, 'b> {
        SubCommand::with_name("generate")
            .about("Generates genesis configuration")
            .arg(Arg::with_name("OUTPUT_DIR")
                     .short("o")
                     .long("output-dir")
                     .value_name("OUTPUT_DIR")
                     .required(true)
                     .takes_value(true))
            .arg(Arg::with_name("START_PORT")
                     .short("p")
                     .long("start-port")
                     .value_name("START_PORT")
                     .required(false)
                     .takes_value(true))
            .arg(Arg::with_name("COUNT")
                     .help("Validators count")
                     .required(true)
                     .index(1))
    }

    pub fn output_dir(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("OUTPUT_DIR").unwrap())
    }

    pub fn validators_count(matches: &'a ArgMatches<'a>) -> u8 {
        matches.value_of("COUNT").unwrap().parse().unwrap()
    }

    pub fn start_port(matches: &'a ArgMatches<'a>) -> Option<u16> {
        matches
            .value_of("START_PORT")
            .map(|p| p.parse().unwrap())
    }

    pub fn execute(matches: &'a ArgMatches<'a>) {
        let dir = Self::output_dir(matches);
        let count = Self::validators_count(matches);
        let start_port = Self::start_port(matches).unwrap_or_else(|| 2000);

        let dir = dir.join("validators");
        if !dir.exists() {
            fs::create_dir_all(&dir).unwrap();
        }

        let configs = generate_testnet_config(count, start_port);
        for (idx, cfg) in configs.into_iter().enumerate() {
            let file_name = format!("{}.toml", idx);
            ConfigFile::save(&cfg, &dir.join(file_name)).unwrap();
        }
    }
}

pub struct RunCommand<'a, 'b>
    where 'a: 'b
{
    _p: PhantomData<App<'a, 'b>>,
}

impl<'a, 'b> RunCommand<'a, 'b>
    where 'a: 'b
{
    pub fn new() -> App<'a, 'b> {
        SubCommand::with_name("run")
            .arg(Arg::with_name("NODE_CONFIG_PATH")
                     .short("c")
                     .long("node-config")
                     .value_name("NODE_CONFIG_PATH")
                     .help("Path to node configuration file")
                     .required(true)
                     .takes_value(true))
            .arg(Arg::with_name("LEVELDB_PATH")
                     .short("d")
                     .long("leveldb-path")
                     .value_name("LEVELDB_PATH")
                     .help("Use leveldb database with the given path")
                     .required(false)
                     .takes_value(true))
    }

    pub fn node_config_path(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("NODE_CONFIG_PATH").unwrap())
    }

    pub fn node_config(matches: &'a ArgMatches<'a>) -> NodeConfig {
        let path = Self::node_config_path(matches);
        ConfigFile::load(path).unwrap()
    }

    pub fn leveldb_path(matches: &'a ArgMatches<'a>) -> Option<&'a Path> {
        matches.value_of("LEVELDB_PATH").map(Path::new)
    }

    #[cfg(not(feature="memorydb"))]
    pub fn db(matches: &'a ArgMatches<'a>) -> Storage {
        use exonum::storage::{LevelDB, LevelDBOptions};

        let path = Self::leveldb_path(matches).unwrap();
        let mut options = LevelDBOptions::new();
        options.create_if_missing = true;
        LevelDB::new(path, options).unwrap()
    }

    #[cfg(feature="memorydb")]
    pub fn db(_: &'a ArgMatches<'a>) -> Storage {
        use exonum::storage::MemoryDB;
        MemoryDB::new()
    }
}

fn has_colors() -> bool {
    use term::terminfo::TerminfoTerminal;
    use term::Terminal;
    use std::io;

    let out = io::stderr();
    if let Some(term) = TerminfoTerminal::new(out) {
        term.supports_color()
    } else {
        false
    }
}

pub fn init_logger() -> Result<(), SetLoggerError> {
    let format = |record: &LogRecord| {
        let ts = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
        let secs = ts.as_secs().to_string();
        let millis = (ts.subsec_nanos() as u64 / 1000000).to_string();

        let module = record.location().module_path();
        let file = record.location().file();
        let line = record.location().line();

        let source_path;
        let verbose_src_path;
        if env::var("LOG_VERBOSE_SRC_FILE_LINE").is_ok() {
            let param_parse = env::var("LOG_VERBOSE_SRC_FILE_LINE").unwrap().parse::<bool>();
            if let Ok(flag) = param_parse {
                verbose_src_path = flag;
            } else {
                verbose_src_path = false;
            }
        } else {
            verbose_src_path = false;
        }

        if verbose_src_path {
            source_path = format!("{}:{}:{}", module, file, line);
        } else {
            source_path = format!("{}", module);
        }

        if has_colors() {
            let level = match record.level() {
                LogLevel::Error => "ERROR".red(),
                LogLevel::Warn => "WARN".yellow(),
                LogLevel::Info => "INFO".green(),
                LogLevel::Debug => "DEBUG".cyan(),
                LogLevel::Trace => "TRACE".white(),
            };
            format!("[{} : {}] - [ {} ] - {} - {}",
                    secs.bold(),
                    millis.bold(),
                    level,
                    &source_path,
                    record.args())
        } else {
            let level = match record.level() {
                LogLevel::Error => "ERROR",
                LogLevel::Warn => "WARN",
                LogLevel::Info => "INFO",
                LogLevel::Debug => "DEBUG",
                LogLevel::Trace => "TRACE",
            };
            format!("[{} : {}] - [ {} ] - {} - {}",
                    secs,
                    millis,
                    level,
                    &source_path,
                    record.args())
        }
    };

    let mut builder = LogBuilder::new();
    builder.format(format);

    if env::var("RUST_LOG").is_ok() {
        builder.parse(&env::var("RUST_LOG").unwrap());
    }

    builder.init()
}

pub fn generate_testnet_config(count: u8, start_port: u16) -> Vec<NodeConfig> {
    let validators = (0..count as usize)
        .map(|_| gen_keypair())
        .collect::<Vec<_>>();
    let genesis = GenesisConfig::new(validators.iter().map(|x| x.0));
    let peers = (0..validators.len())
        .map(|x| {
                 format!("127.0.0.1:{}", start_port + x as u16)
                     .parse()
                     .unwrap()
             })
        .collect::<Vec<_>>();

    validators
        .into_iter()
        .enumerate()
        .map(|(idx, validator)| {
            NodeConfig {
                listen_address: peers[idx],
                network: Default::default(),
                peers: peers.clone(),
                public_key: validator.0,
                secret_key: validator.1,
                genesis: genesis.clone(),
            }
        })
        .collect::<Vec<_>>()
}
<|endoftext|>


<commit_before>trait Foo {
    fn foo();
}

trait Bar : Foo {
    fn bar();
}

fn main() {}

<commit_msg>xfail-fast run-pass/trait-composition-trivial<commit_after>// xfail-fast - ICE
trait Foo {
    fn foo();
}

trait Bar : Foo {
    fn bar();
}

fn main() {}

<|endoftext|>


<commit_before>use path;

use std::borrow::Cow;
use std::path::{Path, PathBuf};

use syn;

pub struct TemplateInput<'a> {
    pub ast: &'a syn::DeriveInput,
    pub meta: TemplateMeta<'a>,
    pub path: PathBuf,
    pub source: Cow<'a, str>,
}

impl<'a> TemplateInput<'a> {
    pub fn new(ast: &'a syn::DeriveInput) -> TemplateInput<'a> {
        let meta = TemplateMeta::new(ast);
        let (path, source) = match meta.source {
            Source::Source(s) => {
                let path = match meta.ext {
                    Some(v) => PathBuf::from(format!("_.{}", v)),
                    None => PathBuf::new(),
                };
                (path, Cow::Borrowed(s))
            },
            Source::Path(s) => {
                let path = path::find_template_from_path(s, None);
                let src = path::get_template_source(&path);
                (path, Cow::Owned(src))
            },
        };
        TemplateInput { ast, meta, path, source }
    }
}

// Holds metadata for the template, based on the `template()` attribute.
pub struct TemplateMeta<'a> {
    source: Source<'a>,
    pub print: Print,
    pub escaping: EscapeMode,
    pub ext: Option<&'a str>,
}

impl<'a> TemplateMeta<'a> {
    fn new(ast: &'a syn::DeriveInput) -> TemplateMeta<'a> {
        let attr = ast.attrs.iter().find(|a| a.name() == "template");
        if attr.is_none() {
            let msg = format!("'template' attribute not found on struct '{}'",
                              ast.ident.as_ref());
            panic!(msg);
        }

        let attr = attr.unwrap();
        let mut source = None;
        let mut print = Print::None;
        let mut escaping = None;
        let mut ext = None;
        if let syn::MetaItem::List(_, ref inner) = attr.value {
            for nm_item in inner {
                if let syn::NestedMetaItem::MetaItem(ref item) = *nm_item {
                    if let syn::MetaItem::NameValue(ref key, ref val) = *item {
                        match key.as_ref() {
                            "path" => if let syn::Lit::Str(ref s, _) = *val {
                                if source.is_some() {
                                    panic!("must specify 'source' or 'path', not both");
                                }
                                source = Some(Source::Path(s.as_ref()));
                            } else {
                                panic!("template path must be string literal");
                            },
                            "source" => if let syn::Lit::Str(ref s, _) = *val {
                                if source.is_some() {
                                    panic!("must specify 'source' or 'path', not both");
                                }
                                source = Some(Source::Source(s.as_ref()));
                            } else {
                                panic!("template source must be string literal");
                            },
                            "print" => if let syn::Lit::Str(ref s, _) = *val {
                                print = (s.as_ref() as &str).into();
                            } else {
                                panic!("print value must be string literal");
                            },
                            "escape" => if let syn::Lit::Str(ref s, _) = *val {
                                escaping = Some((s.as_ref() as &str).into());
                            } else {
                                panic!("escape value must be string literal");
                            },
                            "ext" => if let syn::Lit::Str(ref s, _) = *val {
                                ext = Some((s.as_ref() as &str).into());
                            } else {
                                panic!("ext value must be string literal");
                            },
                            _ => { panic!("unsupported annotation key found") }
                        }
                    }
                }
            }
        }

        let source = source.expect("template path or source not found in attributes");
        match (&source, ext.is_some()) {
            (&Source::Path(_), true) => {
                panic!("'ext' attribute cannot be used with 'path' attribute")
            },
            (&Source::Source(_), false) => {
                panic!("must include 'ext' attribute when using 'source' attribute")
            },
            _ => {},
        }
        let escaping = match escaping {
            Some(m) => m,
            None => {
                let ext = match source {
                    Source::Path(p) => {
                        Path::new(p).extension().map(|s| s.to_str().unwrap()).unwrap_or("")
                    },
                    Source::Source(_) => ext.unwrap(), // Already panicked if None
                };
                if HTML_EXTENSIONS.contains(&ext) {
                    EscapeMode::Html
                } else {
                    EscapeMode::None
                }
            }
        };
        TemplateMeta { source, print, escaping, ext }
    }
}

enum Source<'a> {
    Path(&'a str),
    Source(&'a str),
}

#[derive(PartialEq)]
pub enum EscapeMode {
    Html,
    None,
}

impl<'a> From<&'a str> for EscapeMode {
    fn from(s: &'a str) -> EscapeMode {
        use self::EscapeMode::*;
        match s {
            "html" => Html,
            "none" => None,
            v => panic!("invalid value for escape option: {}", v),
        }
    }
}

#[derive(PartialEq)]
pub enum Print {
    All,
    Ast,
    Code,
    None,
}

impl<'a> From<&'a str> for Print {
    fn from(s: &'a str) -> Print {
        use self::Print::*;
        match s {
            "all" => All,
            "ast" => Ast,
            "code" => Code,
            "none" => None,
            v => panic!("invalid value for print option: {}", v),
        }
    }
}

const HTML_EXTENSIONS: [&str; 3] = ["html", "htm", "xml"];
<commit_msg>Improve error about unsupported annotation key<commit_after>use path;

use std::borrow::Cow;
use std::path::{Path, PathBuf};

use syn;

pub struct TemplateInput<'a> {
    pub ast: &'a syn::DeriveInput,
    pub meta: TemplateMeta<'a>,
    pub path: PathBuf,
    pub source: Cow<'a, str>,
}

impl<'a> TemplateInput<'a> {
    pub fn new(ast: &'a syn::DeriveInput) -> TemplateInput<'a> {
        let meta = TemplateMeta::new(ast);
        let (path, source) = match meta.source {
            Source::Source(s) => {
                let path = match meta.ext {
                    Some(v) => PathBuf::from(format!("_.{}", v)),
                    None => PathBuf::new(),
                };
                (path, Cow::Borrowed(s))
            },
            Source::Path(s) => {
                let path = path::find_template_from_path(s, None);
                let src = path::get_template_source(&path);
                (path, Cow::Owned(src))
            },
        };
        TemplateInput { ast, meta, path, source }
    }
}

// Holds metadata for the template, based on the `template()` attribute.
pub struct TemplateMeta<'a> {
    source: Source<'a>,
    pub print: Print,
    pub escaping: EscapeMode,
    pub ext: Option<&'a str>,
}

impl<'a> TemplateMeta<'a> {
    fn new(ast: &'a syn::DeriveInput) -> TemplateMeta<'a> {
        let attr = ast.attrs.iter().find(|a| a.name() == "template");
        if attr.is_none() {
            let msg = format!("'template' attribute not found on struct '{}'",
                              ast.ident.as_ref());
            panic!(msg);
        }

        let attr = attr.unwrap();
        let mut source = None;
        let mut print = Print::None;
        let mut escaping = None;
        let mut ext = None;
        if let syn::MetaItem::List(_, ref inner) = attr.value {
            for nm_item in inner {
                if let syn::NestedMetaItem::MetaItem(ref item) = *nm_item {
                    if let syn::MetaItem::NameValue(ref key, ref val) = *item {
                        match key.as_ref() {
                            "path" => if let syn::Lit::Str(ref s, _) = *val {
                                if source.is_some() {
                                    panic!("must specify 'source' or 'path', not both");
                                }
                                source = Some(Source::Path(s.as_ref()));
                            } else {
                                panic!("template path must be string literal");
                            },
                            "source" => if let syn::Lit::Str(ref s, _) = *val {
                                if source.is_some() {
                                    panic!("must specify 'source' or 'path', not both");
                                }
                                source = Some(Source::Source(s.as_ref()));
                            } else {
                                panic!("template source must be string literal");
                            },
                            "print" => if let syn::Lit::Str(ref s, _) = *val {
                                print = (s.as_ref() as &str).into();
                            } else {
                                panic!("print value must be string literal");
                            },
                            "escape" => if let syn::Lit::Str(ref s, _) = *val {
                                escaping = Some((s.as_ref() as &str).into());
                            } else {
                                panic!("escape value must be string literal");
                            },
                            "ext" => if let syn::Lit::Str(ref s, _) = *val {
                                ext = Some((s.as_ref() as &str).into());
                            } else {
                                panic!("ext value must be string literal");
                            },
                            attr @ _ => { panic!("unsupported annotation key '{}' found", attr) }
                        }
                    }
                }
            }
        }

        let source = source.expect("template path or source not found in attributes");
        match (&source, ext.is_some()) {
            (&Source::Path(_), true) => {
                panic!("'ext' attribute cannot be used with 'path' attribute")
            },
            (&Source::Source(_), false) => {
                panic!("must include 'ext' attribute when using 'source' attribute")
            },
            _ => {},
        }
        let escaping = match escaping {
            Some(m) => m,
            None => {
                let ext = match source {
                    Source::Path(p) => {
                        Path::new(p).extension().map(|s| s.to_str().unwrap()).unwrap_or("")
                    },
                    Source::Source(_) => ext.unwrap(), // Already panicked if None
                };
                if HTML_EXTENSIONS.contains(&ext) {
                    EscapeMode::Html
                } else {
                    EscapeMode::None
                }
            }
        };
        TemplateMeta { source, print, escaping, ext }
    }
}

enum Source<'a> {
    Path(&'a str),
    Source(&'a str),
}

#[derive(PartialEq)]
pub enum EscapeMode {
    Html,
    None,
}

impl<'a> From<&'a str> for EscapeMode {
    fn from(s: &'a str) -> EscapeMode {
        use self::EscapeMode::*;
        match s {
            "html" => Html,
            "none" => None,
            v => panic!("invalid value for escape option: {}", v),
        }
    }
}

#[derive(PartialEq)]
pub enum Print {
    All,
    Ast,
    Code,
    None,
}

impl<'a> From<&'a str> for Print {
    fn from(s: &'a str) -> Print {
        use self::Print::*;
        match s {
            "all" => All,
            "ast" => Ast,
            "code" => Code,
            "none" => None,
            v => panic!("invalid value for print option: {}", v),
        }
    }
}

const HTML_EXTENSIONS: [&str; 3] = ["html", "htm", "xml"];
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

use std::rc::*;

///
/// Identifies a state in a state machine
///
pub type StateId = u32;

///
/// Trait implemented by objects that represent a state machine, whose transitions depend on a particular symbol type
///
/// These state machines can be nondeterministic - which is to say, have more than one transition per state. They always
/// start in state 0.
///
pub trait StateMachine<InputSymbol, OutputSymbol> {
    ///
    /// Returns the number of states in this state machine
    ///
    fn count_states(&self) -> StateId;

    ///
    /// Returns the transitions for a particular symbol
    ///
    fn get_transitions_for_state(&self, state: StateId) -> Vec<(InputSymbol, StateId)>;

    ///
    /// If a state is an accepting state, then this returns the output symbol that should be produced if this is the longest match
    ///
    fn output_symbol_for_state(&self, state: StateId) -> Option<OutputSymbol>;
}

///
/// Trait used to indicate that a particular state machine is deterministic (has at most one
/// transition per symbol from the original)
///
pub trait DeterministicStateMachine<InputSymbol, OutputSymbol> : StateMachine<InputSymbol, OutputSymbol> { }

///
/// Any reference to a state machine is also a state machine
///
impl<InputSymbol, OutputSymbol> StateMachine<InputSymbol, OutputSymbol> for Rc<StateMachine<InputSymbol, OutputSymbol>> {
    #[inline]
    fn count_states(&self) -> StateId {
        (**self).count_states()
    }

    #[inline]
    fn get_transitions_for_state(&self, state: StateId) -> Vec<(InputSymbol, StateId)> {
        (**self).get_transitions_for_state(state)
    }

    #[inline]
    fn output_symbol_for_state(&self, state: StateId) -> Option<OutputSymbol> {
        (**self).output_symbol_for_state(state)
    }
}

impl<InputSymbol, OutputSymbol> StateMachine<InputSymbol, OutputSymbol> for Rc<DeterministicStateMachine<InputSymbol, OutputSymbol>> {
    #[inline]
    fn count_states(&self) -> StateId {
        (**self).count_states()
    }

    #[inline]
    fn get_transitions_for_state(&self, state: StateId) -> Vec<(InputSymbol, StateId)> {
        (**self).get_transitions_for_state(state)
    }

    #[inline]
    fn output_symbol_for_state(&self, state: StateId) -> Option<OutputSymbol> {
        (**self).output_symbol_for_state(state)
    }
}

impl<InputSymbol, OutputSymbol> DeterministicStateMachine<InputSymbol, OutputSymbol> for Rc<DeterministicStateMachine<InputSymbol, OutputSymbol>> {
}
<commit_msg>Add a mutable trait for the state machine<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

use std::rc::*;

///
/// Identifies a state in a state machine
///
pub type StateId = u32;

///
/// Trait implemented by objects that represent a state machine, whose transitions depend on a particular symbol type
///
/// These state machines can be nondeterministic - which is to say, have more than one transition per state. They always
/// start in state 0.
///
pub trait StateMachine<InputSymbol, OutputSymbol> {
    ///
    /// Returns the number of states in this state machine
    ///
    fn count_states(&self) -> StateId;

    ///
    /// Returns the transitions for a particular symbol
    ///
    fn get_transitions_for_state(&self, state: StateId) -> Vec<(InputSymbol, StateId)>;

    ///
    /// If a state is an accepting state, then this returns the output symbol that should be produced if this is the longest match
    ///
    fn output_symbol_for_state(&self, state: StateId) -> Option<OutputSymbol>;
}

///
/// Trait implemented by state machines that can be altered
///
pub trait MutableStateMachine<InputSymbol, OutputSymbol> : StateMachine<InputSymbol, OutputSymbol> {
    ///
    /// Adds a transition from a particular state to another on seeing a symbol
    ///
    fn add_transition(&mut self, state: StateId, forSymbol: InputSymbol, newState: StateId);

    ///
    /// Sets the output symbol to use for a particular state
    ///
    fn set_output_symbol(&mut self, state: StateId, newOutputSymbol: OutputSymbol);
}

///
/// Trait used to indicate that a particular state machine is deterministic (has at most one
/// transition per symbol from the original)
///
pub trait DeterministicStateMachine<InputSymbol, OutputSymbol> : StateMachine<InputSymbol, OutputSymbol> { }

///
/// Any reference to a state machine is also a state machine
///
impl<InputSymbol, OutputSymbol> StateMachine<InputSymbol, OutputSymbol> for Rc<StateMachine<InputSymbol, OutputSymbol>> {
    #[inline]
    fn count_states(&self) -> StateId {
        (**self).count_states()
    }

    #[inline]
    fn get_transitions_for_state(&self, state: StateId) -> Vec<(InputSymbol, StateId)> {
        (**self).get_transitions_for_state(state)
    }

    #[inline]
    fn output_symbol_for_state(&self, state: StateId) -> Option<OutputSymbol> {
        (**self).output_symbol_for_state(state)
    }
}

impl<InputSymbol, OutputSymbol> StateMachine<InputSymbol, OutputSymbol> for Rc<DeterministicStateMachine<InputSymbol, OutputSymbol>> {
    #[inline]
    fn count_states(&self) -> StateId {
        (**self).count_states()
    }

    #[inline]
    fn get_transitions_for_state(&self, state: StateId) -> Vec<(InputSymbol, StateId)> {
        (**self).get_transitions_for_state(state)
    }

    #[inline]
    fn output_symbol_for_state(&self, state: StateId) -> Option<OutputSymbol> {
        (**self).output_symbol_for_state(state)
    }
}

impl<InputSymbol, OutputSymbol> DeterministicStateMachine<InputSymbol, OutputSymbol> for Rc<DeterministicStateMachine<InputSymbol, OutputSymbol>> {
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2020 Fabian Schuiki

//! A mapping from node IDs to AST nodes.

use crate::ast;
use crate::common::source::Span;
use crate::common::util::{HasDesc, HasSpan};
use crate::common::NodeId;
use crate::crate_prelude::*;
use std::cell::RefCell;
use std::collections::HashMap;

#[derive(Default)]
pub struct AstMap<'ast> {
    map: RefCell<HashMap<NodeId, AstNode<'ast>>>,
}

impl<'ast> AstMap<'ast> {
    /// Insert an AST node into the map.
    pub fn set(&self, id: NodeId, node: impl Into<AstNode<'ast>>) {
        let node = node.into();
        self.map.borrow_mut().insert(id, node);
    }

    /// Retrieve an AST node from the map.
    pub fn get(&self, id: NodeId) -> Option<AstNode<'ast>> {
        self.map.borrow().get(&id).cloned()
    }
}

/// A reference to an AST node.
///
/// This enum essentially provides a wrapper around typed references to AST
/// nodes. It allows code to obtain a generic reference to an AST node and then
/// match on the actual type that was provided.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AstNode<'ast> {
    /// A module.
    Module(&'ast ast::ModDecl<'ast>),
    /// A module or interface port placeholder (defined in HIR).
    Port(Span),
    /// A type.
    Type(&'ast ast::Type<'ast>),
    /// An expression.
    Expr(&'ast ast::Expr<'ast>),
    /// The module/interface name and parameters of an instantiation.
    InstTarget(&'ast ast::Inst<'ast>),
    /// An instance name and reference to its target.
    Inst(&'ast ast::InstName<'ast>, NodeId),
    /// A type parameter.
    TypeParam(&'ast ast::ParamDecl<'ast>, &'ast ast::ParamTypeDecl<'ast>),
    /// A value parameter.
    ValueParam(&'ast ast::ParamDecl<'ast>, &'ast ast::ParamValueDecl<'ast>),
    /// A type or expression.
    TypeOrExpr(&'ast ast::TypeOrExpr<'ast>),
    /// A variable declaration.
    VarDecl(
        &'ast ast::VarDeclName<'ast>,
        &'ast ast::VarDecl<'ast>,
        NodeId,
    ),
    /// A net declaration.
    NetDecl(
        &'ast ast::VarDeclName<'ast>,
        &'ast ast::NetDecl<'ast>,
        NodeId,
    ),
    /// A procedure.
    Proc(&'ast ast::Procedure<'ast>),
    /// A statement.
    Stmt(&'ast ast::Stmt<'ast>),
    /// An event expression.
    EventExpr(&'ast ast::EventExpr<'ast>),
    /// An if-generate statement.
    GenIf(&'ast ast::GenerateIf<'ast>),
    /// A for-generate statement.
    GenFor(&'ast ast::GenerateFor<'ast>),
    /// A case-generate statement.
    GenCase(&'ast ast::GenerateCase),
    /// A genvar declaration.
    GenvarDecl(&'ast ast::GenvarDecl<'ast>),
    /// A typedef.
    Typedef(&'ast ast::Typedef<'ast>),
    /// A continuous assignment.
    ContAssign(
        &'ast ast::ContAssign<'ast>,
        &'ast ast::Expr<'ast>,
        &'ast ast::Expr<'ast>,
    ),
    /// A struct member.
    StructMember(
        &'ast ast::VarDeclName<'ast>,
        &'ast ast::StructMember<'ast>,
        NodeId,
    ),
    /// A package.
    Package(&'ast ast::PackageDecl<'ast>),
    /// An enum variant, given as `(variant, enum_def, index)`.
    EnumVariant(&'ast ast::EnumName<'ast>, NodeId, usize),
    /// An import.
    Import(&'ast ast::ImportItem<'ast>),
    /// A subroutine declaration.
    SubroutineDecl(&'ast ast::SubroutineDecl<'ast>),
    /// An interface.
    Interface(&'ast ast::IntfDecl<'ast>),
}

impl<'a> AstNode<'a> {
    /// Convert this `AstNode` to a `AnyNode`.
    pub fn get_any(&self) -> Option<&dyn AnyNode<'a>> {
        match *self {
            AstNode::Module(x) => Some(x),
            AstNode::Port(_) => None,
            AstNode::Type(x) => Some(x),
            AstNode::Expr(x) => Some(x),
            // AstNode::InstTarget(x) => Some(x),
            // AstNode::Inst(x, _) => Some(x),
            AstNode::TypeParam(_, x) => Some(x),
            AstNode::ValueParam(_, x) => Some(x),
            AstNode::TypeOrExpr(x) => Some(x),
            AstNode::VarDecl(x, _, _) => Some(x),
            // AstNode::NetDecl(x, _, _) => Some(x),
            // AstNode::Proc(x) => Some(x),
            // AstNode::Stmt(x) => Some(x),
            // AstNode::EventExpr(x) => Some(x),
            // AstNode::GenIf(x) => Some(x),
            // AstNode::GenFor(x) => Some(x),
            // AstNode::GenCase(x) => Some(x),
            AstNode::GenvarDecl(x) => Some(x),
            AstNode::Typedef(x) => Some(x),
            // AstNode::ContAssign(x, _, _) => Some(x),
            // AstNode::StructMember(x, _, _) => Some(x),
            AstNode::Package(x) => Some(x),
            AstNode::EnumVariant(x, _, _) => Some(x),
            AstNode::Import(x) => Some(x),
            AstNode::SubroutineDecl(x) => Some(x),
            AstNode::Interface(x) => Some(x),
            _ => None,
        }
    }
}

impl<'ast> HasSpan for AstNode<'ast> {
    fn span(&self) -> Span {
        match *self {
            AstNode::Module(x) => x.span(),
            AstNode::Port(x) => x,
            AstNode::Type(x) => x.span(),
            AstNode::Expr(x) => x.span(),
            AstNode::InstTarget(x) => x.span(),
            AstNode::Inst(x, _) => x.span(),
            AstNode::TypeParam(x, _) => x.span(),
            AstNode::ValueParam(x, _) => x.span(),
            AstNode::TypeOrExpr(x) => x.span(),
            AstNode::VarDecl(_, x, _) => x.span(),
            AstNode::NetDecl(_, x, _) => x.span(),
            AstNode::Proc(x) => x.span(),
            AstNode::Stmt(x) => x.span(),
            AstNode::EventExpr(x) => x.span(),
            AstNode::GenIf(x) => x.span(),
            AstNode::GenFor(x) => x.span(),
            AstNode::GenCase(x) => x.span(),
            AstNode::GenvarDecl(x) => x.span(),
            AstNode::Typedef(x) => x.span(),
            AstNode::ContAssign(x, _, _) => x.span(),
            AstNode::StructMember(_, x, _) => x.span(),
            AstNode::Package(x) => x.span(),
            AstNode::EnumVariant(x, _, _) => x.span(),
            AstNode::Import(x) => x.span(),
            AstNode::SubroutineDecl(x) => x.span(),
            AstNode::Interface(x) => x.span(),
        }
    }

    fn human_span(&self) -> Span {
        match *self {
            AstNode::Module(x) => x.human_span(),
            AstNode::Port(x) => x,
            AstNode::Type(x) => x.human_span(),
            AstNode::Expr(x) => x.human_span(),
            AstNode::InstTarget(x) => x.human_span(),
            AstNode::Inst(x, _) => x.human_span(),
            AstNode::TypeParam(_, x) => x.human_span(),
            AstNode::ValueParam(_, x) => x.human_span(),
            AstNode::TypeOrExpr(x) => x.human_span(),
            AstNode::VarDecl(x, _, _) => x.human_span(),
            AstNode::NetDecl(x, _, _) => x.human_span(),
            AstNode::Proc(x) => x.human_span(),
            AstNode::Stmt(x) => x.human_span(),
            AstNode::EventExpr(x) => x.human_span(),
            AstNode::GenIf(x) => x.human_span(),
            AstNode::GenFor(x) => x.human_span(),
            AstNode::GenCase(x) => x.human_span(),
            AstNode::GenvarDecl(x) => x.human_span(),
            AstNode::Typedef(x) => x.human_span(),
            AstNode::ContAssign(x, _, _) => x.human_span(),
            AstNode::StructMember(x, _, _) => x.human_span(),
            AstNode::Package(x) => x.human_span(),
            AstNode::EnumVariant(x, _, _) => x.human_span(),
            AstNode::Import(x) => x.human_span(),
            AstNode::SubroutineDecl(x) => x.human_span(),
            AstNode::Interface(x) => x.human_span(),
        }
    }
}

impl<'ast> HasDesc for AstNode<'ast> {
    fn desc(&self) -> &'static str {
        #[allow(unused_variables)]
        match *self {
            AstNode::Module(x) => "module",
            AstNode::Port(_) => "port",
            AstNode::Type(x) => "type",
            AstNode::Expr(x) => "expression",
            AstNode::InstTarget(x) => x.desc(),
            AstNode::Inst(x, _) => x.desc(),
            AstNode::TypeParam(_, x) => "type parameter",
            AstNode::ValueParam(_, x) => "value parameter",
            AstNode::TypeOrExpr(x) => "type or expression",
            AstNode::VarDecl(x, _, _) => "variable declaration",
            AstNode::NetDecl(x, _, _) => "net declaration",
            AstNode::Proc(x) => x.desc(),
            AstNode::Stmt(x) => x.desc(),
            AstNode::EventExpr(x) => x.desc(),
            AstNode::GenIf(x) => x.desc(),
            AstNode::GenFor(x) => x.desc(),
            AstNode::GenCase(x) => x.desc(),
            AstNode::GenvarDecl(x) => "genvar",
            AstNode::Typedef(x) => "typedef",
            AstNode::ContAssign(x, _, _) => x.desc(),
            AstNode::StructMember(x, _, _) => "struct member",
            AstNode::Package(x) => "package",
            AstNode::EnumVariant(x, _, _) => "enum variant",
            AstNode::Import(x) => "import",
            AstNode::SubroutineDecl(x) => "subroutine declaration",
            AstNode::Interface(x) => "interface",
        }
    }

    fn desc_full(&self) -> String {
        match *self {
            AstNode::Module(x) => x.to_definite_string(),
            AstNode::Port(_) => "port".to_string(),
            AstNode::Type(x) => x.to_definite_string(),
            AstNode::Expr(x) => x.to_definite_string(),
            AstNode::InstTarget(x) => x.desc_full(),
            AstNode::Inst(x, _) => x.desc_full(),
            AstNode::TypeParam(_, x) => x.to_definite_string(),
            AstNode::ValueParam(_, x) => x.to_definite_string(),
            AstNode::TypeOrExpr(x) => x.to_definite_string(),
            AstNode::VarDecl(x, _, _) => x.to_definite_string(),
            AstNode::NetDecl(x, _, _) => x.to_definite_string(),
            AstNode::Proc(x) => x.desc_full(),
            AstNode::Stmt(x) => x.desc_full(),
            AstNode::EventExpr(x) => x.desc_full(),
            AstNode::GenIf(x) => x.desc_full(),
            AstNode::GenFor(x) => x.desc_full(),
            AstNode::GenCase(x) => x.desc_full(),
            AstNode::GenvarDecl(x) => x.to_definite_string(),
            AstNode::Typedef(x) => x.to_definite_string(),
            AstNode::ContAssign(x, _, _) => x.desc_full(),
            AstNode::StructMember(x, _, _) => x.to_definite_string(),
            AstNode::Package(x) => x.to_definite_string(),
            AstNode::EnumVariant(x, _, _) => x.to_definite_string(),
            AstNode::Import(x) => x.to_definite_string(),
            AstNode::SubroutineDecl(x) => x.to_definite_string(),
            AstNode::Interface(x) => x.to_definite_string(),
        }
    }
}
<commit_msg>svlog: Fix lifetime on AstNode to AnyNode conv<commit_after>// Copyright (c) 2016-2020 Fabian Schuiki

//! A mapping from node IDs to AST nodes.

use crate::ast;
use crate::common::source::Span;
use crate::common::util::{HasDesc, HasSpan};
use crate::common::NodeId;
use crate::crate_prelude::*;
use std::cell::RefCell;
use std::collections::HashMap;

#[derive(Default)]
pub struct AstMap<'ast> {
    map: RefCell<HashMap<NodeId, AstNode<'ast>>>,
}

impl<'ast> AstMap<'ast> {
    /// Insert an AST node into the map.
    pub fn set(&self, id: NodeId, node: impl Into<AstNode<'ast>>) {
        let node = node.into();
        self.map.borrow_mut().insert(id, node);
    }

    /// Retrieve an AST node from the map.
    pub fn get(&self, id: NodeId) -> Option<AstNode<'ast>> {
        self.map.borrow().get(&id).cloned()
    }
}

/// A reference to an AST node.
///
/// This enum essentially provides a wrapper around typed references to AST
/// nodes. It allows code to obtain a generic reference to an AST node and then
/// match on the actual type that was provided.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AstNode<'ast> {
    /// A module.
    Module(&'ast ast::ModDecl<'ast>),
    /// A module or interface port placeholder (defined in HIR).
    Port(Span),
    /// A type.
    Type(&'ast ast::Type<'ast>),
    /// An expression.
    Expr(&'ast ast::Expr<'ast>),
    /// The module/interface name and parameters of an instantiation.
    InstTarget(&'ast ast::Inst<'ast>),
    /// An instance name and reference to its target.
    Inst(&'ast ast::InstName<'ast>, NodeId),
    /// A type parameter.
    TypeParam(&'ast ast::ParamDecl<'ast>, &'ast ast::ParamTypeDecl<'ast>),
    /// A value parameter.
    ValueParam(&'ast ast::ParamDecl<'ast>, &'ast ast::ParamValueDecl<'ast>),
    /// A type or expression.
    TypeOrExpr(&'ast ast::TypeOrExpr<'ast>),
    /// A variable declaration.
    VarDecl(
        &'ast ast::VarDeclName<'ast>,
        &'ast ast::VarDecl<'ast>,
        NodeId,
    ),
    /// A net declaration.
    NetDecl(
        &'ast ast::VarDeclName<'ast>,
        &'ast ast::NetDecl<'ast>,
        NodeId,
    ),
    /// A procedure.
    Proc(&'ast ast::Procedure<'ast>),
    /// A statement.
    Stmt(&'ast ast::Stmt<'ast>),
    /// An event expression.
    EventExpr(&'ast ast::EventExpr<'ast>),
    /// An if-generate statement.
    GenIf(&'ast ast::GenerateIf<'ast>),
    /// A for-generate statement.
    GenFor(&'ast ast::GenerateFor<'ast>),
    /// A case-generate statement.
    GenCase(&'ast ast::GenerateCase),
    /// A genvar declaration.
    GenvarDecl(&'ast ast::GenvarDecl<'ast>),
    /// A typedef.
    Typedef(&'ast ast::Typedef<'ast>),
    /// A continuous assignment.
    ContAssign(
        &'ast ast::ContAssign<'ast>,
        &'ast ast::Expr<'ast>,
        &'ast ast::Expr<'ast>,
    ),
    /// A struct member.
    StructMember(
        &'ast ast::VarDeclName<'ast>,
        &'ast ast::StructMember<'ast>,
        NodeId,
    ),
    /// A package.
    Package(&'ast ast::PackageDecl<'ast>),
    /// An enum variant, given as `(variant, enum_def, index)`.
    EnumVariant(&'ast ast::EnumName<'ast>, NodeId, usize),
    /// An import.
    Import(&'ast ast::ImportItem<'ast>),
    /// A subroutine declaration.
    SubroutineDecl(&'ast ast::SubroutineDecl<'ast>),
    /// An interface.
    Interface(&'ast ast::IntfDecl<'ast>),
}

impl<'a> AstNode<'a> {
    /// Convert this `AstNode` to a `AnyNode`.
    pub fn get_any(&self) -> Option<&'a dyn AnyNode<'a>> {
        match *self {
            AstNode::Module(x) => Some(x),
            AstNode::Port(_) => None,
            AstNode::Type(x) => Some(x),
            AstNode::Expr(x) => Some(x),
            // AstNode::InstTarget(x) => Some(x),
            // AstNode::Inst(x, _) => Some(x),
            AstNode::TypeParam(_, x) => Some(x),
            AstNode::ValueParam(_, x) => Some(x),
            AstNode::TypeOrExpr(x) => Some(x),
            AstNode::VarDecl(x, _, _) => Some(x),
            // AstNode::NetDecl(x, _, _) => Some(x),
            // AstNode::Proc(x) => Some(x),
            // AstNode::Stmt(x) => Some(x),
            // AstNode::EventExpr(x) => Some(x),
            // AstNode::GenIf(x) => Some(x),
            // AstNode::GenFor(x) => Some(x),
            // AstNode::GenCase(x) => Some(x),
            AstNode::GenvarDecl(x) => Some(x),
            AstNode::Typedef(x) => Some(x),
            // AstNode::ContAssign(x, _, _) => Some(x),
            // AstNode::StructMember(x, _, _) => Some(x),
            AstNode::Package(x) => Some(x),
            AstNode::EnumVariant(x, _, _) => Some(x),
            AstNode::Import(x) => Some(x),
            AstNode::SubroutineDecl(x) => Some(x),
            AstNode::Interface(x) => Some(x),
            _ => None,
        }
    }
}

impl<'ast> HasSpan for AstNode<'ast> {
    fn span(&self) -> Span {
        match *self {
            AstNode::Module(x) => x.span(),
            AstNode::Port(x) => x,
            AstNode::Type(x) => x.span(),
            AstNode::Expr(x) => x.span(),
            AstNode::InstTarget(x) => x.span(),
            AstNode::Inst(x, _) => x.span(),
            AstNode::TypeParam(x, _) => x.span(),
            AstNode::ValueParam(x, _) => x.span(),
            AstNode::TypeOrExpr(x) => x.span(),
            AstNode::VarDecl(_, x, _) => x.span(),
            AstNode::NetDecl(_, x, _) => x.span(),
            AstNode::Proc(x) => x.span(),
            AstNode::Stmt(x) => x.span(),
            AstNode::EventExpr(x) => x.span(),
            AstNode::GenIf(x) => x.span(),
            AstNode::GenFor(x) => x.span(),
            AstNode::GenCase(x) => x.span(),
            AstNode::GenvarDecl(x) => x.span(),
            AstNode::Typedef(x) => x.span(),
            AstNode::ContAssign(x, _, _) => x.span(),
            AstNode::StructMember(_, x, _) => x.span(),
            AstNode::Package(x) => x.span(),
            AstNode::EnumVariant(x, _, _) => x.span(),
            AstNode::Import(x) => x.span(),
            AstNode::SubroutineDecl(x) => x.span(),
            AstNode::Interface(x) => x.span(),
        }
    }

    fn human_span(&self) -> Span {
        match *self {
            AstNode::Module(x) => x.human_span(),
            AstNode::Port(x) => x,
            AstNode::Type(x) => x.human_span(),
            AstNode::Expr(x) => x.human_span(),
            AstNode::InstTarget(x) => x.human_span(),
            AstNode::Inst(x, _) => x.human_span(),
            AstNode::TypeParam(_, x) => x.human_span(),
            AstNode::ValueParam(_, x) => x.human_span(),
            AstNode::TypeOrExpr(x) => x.human_span(),
            AstNode::VarDecl(x, _, _) => x.human_span(),
            AstNode::NetDecl(x, _, _) => x.human_span(),
            AstNode::Proc(x) => x.human_span(),
            AstNode::Stmt(x) => x.human_span(),
            AstNode::EventExpr(x) => x.human_span(),
            AstNode::GenIf(x) => x.human_span(),
            AstNode::GenFor(x) => x.human_span(),
            AstNode::GenCase(x) => x.human_span(),
            AstNode::GenvarDecl(x) => x.human_span(),
            AstNode::Typedef(x) => x.human_span(),
            AstNode::ContAssign(x, _, _) => x.human_span(),
            AstNode::StructMember(x, _, _) => x.human_span(),
            AstNode::Package(x) => x.human_span(),
            AstNode::EnumVariant(x, _, _) => x.human_span(),
            AstNode::Import(x) => x.human_span(),
            AstNode::SubroutineDecl(x) => x.human_span(),
            AstNode::Interface(x) => x.human_span(),
        }
    }
}

impl<'ast> HasDesc for AstNode<'ast> {
    fn desc(&self) -> &'static str {
        #[allow(unused_variables)]
        match *self {
            AstNode::Module(x) => "module",
            AstNode::Port(_) => "port",
            AstNode::Type(x) => "type",
            AstNode::Expr(x) => "expression",
            AstNode::InstTarget(x) => x.desc(),
            AstNode::Inst(x, _) => x.desc(),
            AstNode::TypeParam(_, x) => "type parameter",
            AstNode::ValueParam(_, x) => "value parameter",
            AstNode::TypeOrExpr(x) => "type or expression",
            AstNode::VarDecl(x, _, _) => "variable declaration",
            AstNode::NetDecl(x, _, _) => "net declaration",
            AstNode::Proc(x) => x.desc(),
            AstNode::Stmt(x) => x.desc(),
            AstNode::EventExpr(x) => x.desc(),
            AstNode::GenIf(x) => x.desc(),
            AstNode::GenFor(x) => x.desc(),
            AstNode::GenCase(x) => x.desc(),
            AstNode::GenvarDecl(x) => "genvar",
            AstNode::Typedef(x) => "typedef",
            AstNode::ContAssign(x, _, _) => x.desc(),
            AstNode::StructMember(x, _, _) => "struct member",
            AstNode::Package(x) => "package",
            AstNode::EnumVariant(x, _, _) => "enum variant",
            AstNode::Import(x) => "import",
            AstNode::SubroutineDecl(x) => "subroutine declaration",
            AstNode::Interface(x) => "interface",
        }
    }

    fn desc_full(&self) -> String {
        match *self {
            AstNode::Module(x) => x.to_definite_string(),
            AstNode::Port(_) => "port".to_string(),
            AstNode::Type(x) => x.to_definite_string(),
            AstNode::Expr(x) => x.to_definite_string(),
            AstNode::InstTarget(x) => x.desc_full(),
            AstNode::Inst(x, _) => x.desc_full(),
            AstNode::TypeParam(_, x) => x.to_definite_string(),
            AstNode::ValueParam(_, x) => x.to_definite_string(),
            AstNode::TypeOrExpr(x) => x.to_definite_string(),
            AstNode::VarDecl(x, _, _) => x.to_definite_string(),
            AstNode::NetDecl(x, _, _) => x.to_definite_string(),
            AstNode::Proc(x) => x.desc_full(),
            AstNode::Stmt(x) => x.desc_full(),
            AstNode::EventExpr(x) => x.desc_full(),
            AstNode::GenIf(x) => x.desc_full(),
            AstNode::GenFor(x) => x.desc_full(),
            AstNode::GenCase(x) => x.desc_full(),
            AstNode::GenvarDecl(x) => x.to_definite_string(),
            AstNode::Typedef(x) => x.to_definite_string(),
            AstNode::ContAssign(x, _, _) => x.desc_full(),
            AstNode::StructMember(x, _, _) => x.to_definite_string(),
            AstNode::Package(x) => x.to_definite_string(),
            AstNode::EnumVariant(x, _, _) => x.to_definite_string(),
            AstNode::Import(x) => x.to_definite_string(),
            AstNode::SubroutineDecl(x) => x.to_definite_string(),
            AstNode::Interface(x) => x.to_definite_string(),
        }
    }
}
<|endoftext|>