<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! An adapter providing access to IP cameras. Currently only the following IP cameras are
//! supported: `DLink DCS-5010L`, `DLink DCS-5020L` and `DLink DCS-5025`.
//!

extern crate serde_json;

mod api;
mod upnp_listener;

use config_store::ConfigService;
use foxbox_taxonomy::api::{Error, InternalError, User};
use foxbox_taxonomy::channel::*;
use foxbox_taxonomy::manager::*;
use foxbox_taxonomy::services::*;
use foxbox_taxonomy::values::{ Value, Json, Binary, Type, TypeError};
use traits::Controller;
use self::api::*;
use self::upnp_listener::IpCameraUpnpListener;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};

const CUSTOM_PROPERTY_MANUFACTURER: &'static str = "manufacturer";
const CUSTOM_PROPERTY_MODEL: &'static str = "model";
const CUSTOM_PROPERTY_NAME: &'static str = "name";
const CUSTOM_PROPERTY_URL: &'static str = "url";
const CUSTOM_PROPERTY_UDN: &'static str = "udn";

static ADAPTER_NAME: &'static str = "IP Camera adapter";
static ADAPTER_VENDOR: &'static str = "team@link.mozilla.org";
static ADAPTER_VERSION: [u32; 4] = [0, 0, 0, 0];
static SNAPSHOT_DIR: &'static str = "snapshots";

pub type IpCameraServiceMap = Arc<Mutex<IpCameraServiceMapInternal>>;

pub struct IpCameraServiceMapInternal {
    getters: HashMap<Id<Channel>, Arc<IpCamera>>,
    setters: HashMap<Id<Channel>, Arc<IpCamera>>,
    snapshot_root: String,
}

pub struct IPCameraAdapter {
    services: IpCameraServiceMap,
}

impl IPCameraAdapter {
    pub fn id() -> Id<AdapterId> {
        Id::new("ip-camera@link.mozilla.org")
    }

    pub fn init<C>(adapt: &Arc<AdapterManager>, controller: C) -> Result<(), Error>
        where C: Controller
    {
        let services = Arc::new(Mutex::new(IpCameraServiceMapInternal {
            getters: HashMap::new(),
            setters: HashMap::new(),
            snapshot_root: controller.get_profile().path_for(SNAPSHOT_DIR),
        }));
        let ip_camera_adapter = Arc::new(IPCameraAdapter {
            services: services.clone(),
        });

        try!(adapt.add_adapter(ip_camera_adapter));

        // The UPNP listener will add camera service for discovered cameras
        let upnp = controller.get_upnp_manager();
        let listener = IpCameraUpnpListener::new(adapt, services, &controller.get_config());
        upnp.add_listener("IpCameraTaxonomy".to_owned(), listener);

        // The UPNP service searches for ssdp:all which the D-Link cameras
        // don't seem to respond to. So we search for this instead, which
        // they do respond to.
        upnp.search(Some("urn:cellvision:service:Null:1".to_owned())).unwrap();
        Ok(())
    }

    pub fn init_service(adapt: &Arc<AdapterManager>, services: IpCameraServiceMap, config: &Arc<ConfigService>,
        udn: &str, url: &str, name: &str, manufacturer: &str, model_name: &str) -> Result<(), Error>
    {
        let service_id = create_service_id(udn);

        let adapter_id = Self::id();
        let mut service = Service::empty(&service_id, &adapter_id);

        service.properties.insert(CUSTOM_PROPERTY_MANUFACTURER.to_owned(),
                                           manufacturer.to_owned());
        service.properties.insert(CUSTOM_PROPERTY_MODEL.to_owned(), model_name.to_owned());
        service.properties.insert(CUSTOM_PROPERTY_NAME.to_owned(), name.to_owned());
        service.properties.insert(CUSTOM_PROPERTY_URL.to_owned(), url.to_owned());
        service.properties.insert(CUSTOM_PROPERTY_UDN.to_owned(), udn.to_owned());
        service.tags.insert(tag_id!(&format!("name:{}", name)));

        // Since the upnp_discover will be called about once very 3 minutes we want to ignore
        // discoveries if the camera is already registered.
        if let Err(error) = adapt.add_service(service) {
            if let Error::InternalError(ref internal_error) = error {
                if let InternalError::DuplicateService(_) = *internal_error {
                    debug!("Found {} @ {} UDN {} (ignoring since it already exists)",
                           model_name,
                           url,
                           udn);
                    return Ok(());
                }
            }

            panic!(error);
        }

        info!("Adding IpCamera {} Manufacturer: {} Model: {} Name: {}",
              udn,
              manufacturer,
              model_name,
              name);

        let getter_image_list_id = create_channel_id("image_list", udn);
        try!(adapt.add_channel(Channel {
            feature: Id::new("camera/x-image-list"),
            supports_fetch: Some(Signature::returns(Maybe::Required(Type::Json))),
            id: getter_image_list_id.clone(),
            service: service_id.clone(),
            adapter: adapter_id.clone(),
            ..Channel::default()
        }));

        let getter_image_newest_id = create_channel_id("image_newest", udn);
        try!(adapt.add_channel(Channel {
            feature: Id::new("camera/x-latest-image"),
            supports_fetch: Some(Signature::returns(Maybe::Required(Type::Binary))),
            id: getter_image_newest_id.clone(),
            service: service_id.clone(),
            adapter: adapter_id.clone(),
            ..Channel::default()
        }));

        let setter_snapshot_id = create_channel_id("snapshot", udn);
        try!(adapt.add_channel(Channel {
            feature: Id::new("camera/store-snapshot"),
            supports_send: Some(Signature::returns(Maybe::Nothing)),
            id: setter_snapshot_id.clone(),
            service: service_id.clone(),
            adapter: adapter_id.clone(),
            ..Channel::default()
        }));

        let channel_username_id = create_channel_id("username", udn);
        try!(adapt.add_channel(Channel {
            id: channel_username_id.clone(),
            service: service_id.clone(),
            adapter: adapter_id.clone(),
            ..USERNAME.clone()
        }));

        let channel_password_id = create_channel_id("password", udn);
        try!(adapt.add_channel(Channel {
            id: channel_password_id.clone(),
            service: service_id.clone(),
            adapter: adapter_id.clone(),
            ..PASSWORD.clone()
        }));

        let mut serv = services.lock().unwrap();
        let camera_obj = try!(IpCamera::new(udn, url, name, &serv.snapshot_root, config));
        let camera = Arc::new(camera_obj);
        serv.getters.insert(getter_image_list_id, camera.clone());
        serv.getters.insert(getter_image_newest_id, camera.clone());
        serv.setters.insert(setter_snapshot_id, camera.clone());
        serv.getters.insert(channel_username_id.clone(), camera.clone());
        serv.setters.insert(channel_username_id, camera.clone());
        serv.getters.insert(channel_password_id.clone(), camera.clone());
        serv.setters.insert(channel_password_id, camera.clone());

        Ok(())
    }
}

impl Adapter for IPCameraAdapter {
    fn id(&self) -> Id<AdapterId> {
        Self::id()
    }

    fn name(&self) -> &str {
        ADAPTER_NAME
    }

    fn vendor(&self) -> &str {
        ADAPTER_VENDOR
    }

    fn version(&self) -> &[u32; 4] {
        &ADAPTER_VERSION
    }

    fn fetch_values(&self,
                    mut set: Vec<Id<Channel>>,
                    _: User)
                    -> ResultMap<Id<Channel>, Option<Value>, Error> {
        set.drain(..).map(|id| {
            let camera = match self.services.lock().unwrap().getters.get(&id) {
                Some(camera) => camera.clone(),
                None => return (id.clone(), Err(Error::InternalError(InternalError::NoSuchChannel(id))))
            };

            if id == camera.username_id {
                let rsp = camera.get_username();
                return (id, Ok(Some(Value::String(Arc::new(rsp)))));
            }

            if id == camera.password_id {
                let rsp = camera.get_password();
                return (id, Ok(Some(Value::String(Arc::new(rsp)))));
            }

            if id == camera.image_list_id {
                let rsp = camera.get_image_list();
                return (id, Ok(Some(Value::Json(Arc::new(Json(serde_json::to_value(&rsp)))))));
            }

            if id == camera.image_newest_id {
                return match camera.get_newest_image() {
                    Ok(rsp) => (id, Ok(Some(Value::Binary(Binary {
                        data: Arc::new(rsp),
                        mimetype: Id::new("image/jpeg")
                    })))),
                    Err(err) => (id, Err(err))
                };
            }

            (id.clone(), Err(Error::InternalError(InternalError::NoSuchChannel(id))))
        }).collect()
    }

    fn send_values(&self, mut values: HashMap<Id<Channel>, Value>, _: User) -> ResultMap<Id<Channel>, (), Error> {
        values.drain().map(|(id, value)| {
            let camera = match self.services.lock().unwrap().setters.get(&id) {
                Some(camera) => camera.clone(),
                None => { return (id, Err(Error::InternalError(InternalError::InvalidInitialService))); }
            };

            if id == camera.username_id {
                if let Value::String(ref username) = value {
                    camera.set_username(username);
                    return (id, Ok(()));
                }
                return (id, Err(Error::TypeError(TypeError {
                                got:value.get_type(),
                                expected: Type::String
                            })))
            }

            if id == camera.password_id {
                if let Value::String(ref password) = value {
                    camera.set_password(password);
                    return (id, Ok(()));
                }
                return (id, Err(Error::TypeError(TypeError {
                                got:value.get_type(),
                                expected: Type::String
                            })))
            }

            if id == camera.snapshot_id {
                return match camera.take_snapshot() {
                    Ok(_) => (id, Ok(())),
                    Err(err) => (id, Err(err))
                };
            }

            (id.clone(), Err(Error::InternalError(InternalError::NoSuchChannel(id))))
        }).collect()
    }
}
<commit_msg>IPCamera: Removing reliance upon Serde's (De)serialize<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! An adapter providing access to IP cameras. Currently only the following IP cameras are
//! supported: `DLink DCS-5010L`, `DLink DCS-5020L` and `DLink DCS-5025`.
//!

extern crate serde_json;

mod api;
mod upnp_listener;

use config_store::ConfigService;
use foxbox_taxonomy::api::{Error, InternalError, User};
use foxbox_taxonomy::channel::*;
use foxbox_taxonomy::manager::*;
use foxbox_taxonomy::services::*;
use foxbox_taxonomy::values::{ Value, Json, Binary, Type, TypeError};
use traits::Controller;
use self::api::*;
use self::upnp_listener::IpCameraUpnpListener;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};

const CUSTOM_PROPERTY_MANUFACTURER: &'static str = "manufacturer";
const CUSTOM_PROPERTY_MODEL: &'static str = "model";
const CUSTOM_PROPERTY_NAME: &'static str = "name";
const CUSTOM_PROPERTY_URL: &'static str = "url";
const CUSTOM_PROPERTY_UDN: &'static str = "udn";

static ADAPTER_NAME: &'static str = "IP Camera adapter";
static ADAPTER_VENDOR: &'static str = "team@link.mozilla.org";
static ADAPTER_VERSION: [u32; 4] = [0, 0, 0, 0];
static SNAPSHOT_DIR: &'static str = "snapshots";

pub type IpCameraServiceMap = Arc<Mutex<IpCameraServiceMapInternal>>;

pub struct IpCameraServiceMapInternal {
    getters: HashMap<Id<Channel>, Arc<IpCamera>>,
    setters: HashMap<Id<Channel>, Arc<IpCamera>>,
    snapshot_root: String,
}

pub struct IPCameraAdapter {
    services: IpCameraServiceMap,
}

impl IPCameraAdapter {
    pub fn id() -> Id<AdapterId> {
        Id::new("ip-camera@link.mozilla.org")
    }

    pub fn init<C>(adapt: &Arc<AdapterManager>, controller: C) -> Result<(), Error>
        where C: Controller
    {
        let services = Arc::new(Mutex::new(IpCameraServiceMapInternal {
            getters: HashMap::new(),
            setters: HashMap::new(),
            snapshot_root: controller.get_profile().path_for(SNAPSHOT_DIR),
        }));
        let ip_camera_adapter = Arc::new(IPCameraAdapter {
            services: services.clone(),
        });

        try!(adapt.add_adapter(ip_camera_adapter));

        // The UPNP listener will add camera service for discovered cameras
        let upnp = controller.get_upnp_manager();
        let listener = IpCameraUpnpListener::new(adapt, services, &controller.get_config());
        upnp.add_listener("IpCameraTaxonomy".to_owned(), listener);

        // The UPNP service searches for ssdp:all which the D-Link cameras
        // don't seem to respond to. So we search for this instead, which
        // they do respond to.
        upnp.search(Some("urn:cellvision:service:Null:1".to_owned())).unwrap();
        Ok(())
    }

    pub fn init_service(adapt: &Arc<AdapterManager>, services: IpCameraServiceMap, config: &Arc<ConfigService>,
        udn: &str, url: &str, name: &str, manufacturer: &str, model_name: &str) -> Result<(), Error>
    {
        let service_id = create_service_id(udn);

        let adapter_id = Self::id();
        let mut service = Service::empty(&service_id, &adapter_id);

        service.properties.insert(CUSTOM_PROPERTY_MANUFACTURER.to_owned(),
                                           manufacturer.to_owned());
        service.properties.insert(CUSTOM_PROPERTY_MODEL.to_owned(), model_name.to_owned());
        service.properties.insert(CUSTOM_PROPERTY_NAME.to_owned(), name.to_owned());
        service.properties.insert(CUSTOM_PROPERTY_URL.to_owned(), url.to_owned());
        service.properties.insert(CUSTOM_PROPERTY_UDN.to_owned(), udn.to_owned());
        service.tags.insert(tag_id!(&format!("name:{}", name)));

        // Since the upnp_discover will be called about once very 3 minutes we want to ignore
        // discoveries if the camera is already registered.
        if let Err(error) = adapt.add_service(service) {
            if let Error::InternalError(ref internal_error) = error {
                if let InternalError::DuplicateService(_) = *internal_error {
                    debug!("Found {} @ {} UDN {} (ignoring since it already exists)",
                           model_name,
                           url,
                           udn);
                    return Ok(());
                }
            }

            panic!(error);
        }

        info!("Adding IpCamera {} Manufacturer: {} Model: {} Name: {}",
              udn,
              manufacturer,
              model_name,
              name);

        let getter_image_list_id = create_channel_id("image_list", udn);
        try!(adapt.add_channel(Channel {
            feature: Id::new("camera/x-image-list"),
            supports_fetch: Some(Signature::returns(Maybe::Required(Type::Json))),
            id: getter_image_list_id.clone(),
            service: service_id.clone(),
            adapter: adapter_id.clone(),
            ..Channel::default()
        }));

        let getter_image_newest_id = create_channel_id("image_newest", udn);
        try!(adapt.add_channel(Channel {
            feature: Id::new("camera/x-latest-image"),
            supports_fetch: Some(Signature::returns(Maybe::Required(Type::Binary))),
            id: getter_image_newest_id.clone(),
            service: service_id.clone(),
            adapter: adapter_id.clone(),
            ..Channel::default()
        }));

        let setter_snapshot_id = create_channel_id("snapshot", udn);
        try!(adapt.add_channel(Channel {
            feature: Id::new("camera/store-snapshot"),
            supports_send: Some(Signature::returns(Maybe::Nothing)),
            id: setter_snapshot_id.clone(),
            service: service_id.clone(),
            adapter: adapter_id.clone(),
            ..Channel::default()
        }));

        let channel_username_id = create_channel_id("username", udn);
        try!(adapt.add_channel(Channel {
            id: channel_username_id.clone(),
            service: service_id.clone(),
            adapter: adapter_id.clone(),
            ..USERNAME.clone()
        }));

        let channel_password_id = create_channel_id("password", udn);
        try!(adapt.add_channel(Channel {
            id: channel_password_id.clone(),
            service: service_id.clone(),
            adapter: adapter_id.clone(),
            ..PASSWORD.clone()
        }));

        let mut serv = services.lock().unwrap();
        let camera_obj = try!(IpCamera::new(udn, url, name, &serv.snapshot_root, config));
        let camera = Arc::new(camera_obj);
        serv.getters.insert(getter_image_list_id, camera.clone());
        serv.getters.insert(getter_image_newest_id, camera.clone());
        serv.setters.insert(setter_snapshot_id, camera.clone());
        serv.getters.insert(channel_username_id.clone(), camera.clone());
        serv.setters.insert(channel_username_id, camera.clone());
        serv.getters.insert(channel_password_id.clone(), camera.clone());
        serv.setters.insert(channel_password_id, camera.clone());

        Ok(())
    }
}

impl Adapter for IPCameraAdapter {
    fn id(&self) -> Id<AdapterId> {
        Self::id()
    }

    fn name(&self) -> &str {
        ADAPTER_NAME
    }

    fn vendor(&self) -> &str {
        ADAPTER_VENDOR
    }

    fn version(&self) -> &[u32; 4] {
        &ADAPTER_VERSION
    }

    fn fetch_values(&self,
                    mut set: Vec<Id<Channel>>,
                    _: User)
                    -> ResultMap<Id<Channel>, Option<Value>, Error> {
        set.drain(..).map(|id| {
            let camera = match self.services.lock().unwrap().getters.get(&id) {
                Some(camera) => camera.clone(),
                None => return (id.clone(), Err(Error::InternalError(InternalError::NoSuchChannel(id))))
            };

            if id == camera.username_id {
                let rsp = camera.get_username();
                return (id, Ok(Some(Value::String(Arc::new(rsp)))));
            }

            if id == camera.password_id {
                let rsp = camera.get_password();
                return (id, Ok(Some(Value::String(Arc::new(rsp)))));
            }

            if id == camera.image_list_id {
                let rsp = camera.get_image_list();
                return (id, Ok(Some(Value::Json(Arc::new(Json(serde_json::to_value(&rsp)))))));
            }

            if id == camera.image_newest_id {
                return match camera.get_newest_image() {
                    Ok(rsp) => (id, Ok(Some(Value::Binary(Binary {
                        data: Arc::new(rsp),
                        mimetype: Id::new("image/jpeg")
                    })))),
                    Err(err) => (id, Err(err))
                };
            }

            (id.clone(), Err(Error::InternalError(InternalError::NoSuchChannel(id))))
        }).collect()
    }

    fn send_values(&self, mut values: HashMap<Id<Channel>, Value>, _: User) -> ResultMap<Id<Channel>, (), Error> {
        values.drain().map(|(id, value)| {
            let camera = match self.services.lock().unwrap().setters.get(&id) {
                Some(camera) => camera.clone(),
                None => { return (id, Err(Error::InternalError(InternalError::InvalidInitialService))); }
            };

            if id == camera.username_id {
                if let Value::String(ref username) = value {
                    camera.set_username(username);
                    return (id, Ok(()));
                }
                return (id, Err(Error::TypeError(TypeError {
                                got:value.get_type().name(),
                                expected: Type::String.name()
                            })))
            }

            if id == camera.password_id {
                if let Value::String(ref password) = value {
                    camera.set_password(password);
                    return (id, Ok(()));
                }
                return (id, Err(Error::TypeError(TypeError {
                                got:value.get_type().name(),
                                expected: Type::String.name()
                            })))
            }

            if id == camera.snapshot_id {
                return match camera.take_snapshot() {
                    Ok(_) => (id, Ok(())),
                    Err(err) => (id, Err(err))
                };
            }

            (id.clone(), Err(Error::InternalError(InternalError::NoSuchChannel(id))))
        }).collect()
    }
}
<|endoftext|>


<commit_before>extern crate "rust-hl-lua" as lua;

use lua::Lua;
use std::io::File;

#[test]
#[should_fail]
fn readerrors() {
    let mut lua = Lua::new();
    let _res: () = lua.execute_from_reader(File::open(&Path::new("/path/to/unexisting/file"))).unwrap();
}
<commit_msg>Fix misc tests<commit_after>extern crate "rust-hl-lua" as lua;

use lua::Lua;
use std::io::fs::File;

#[test]
#[should_fail]
fn readerrors() {
    let mut lua = Lua::new();
    let _res: () = lua.execute_from_reader(File::open(&Path::new("/path/to/unexisting/file"))).unwrap();
}
<|endoftext|>


<commit_before>pub fn binary_search<T>(vector: Vec<T>, value: T) -> Option<usize>
where
    T: PartialOrd,
{
    if vector.is_empty() {
        return None;
    }

    let mut lower_bound: usize = 0;
    let mut upper_bound = vector.len() - 1;
    while lower_bound <= upper_bound {
        let midpoint = (lower_bound + upper_bound) / 2;
        match &vector[midpoint] {
            value_at_midpoint if value_at_midpoint < &value => lower_bound = midpoint + 1,
            value_at_midpoint if value_at_midpoint > &value => {
                if midpoint == 0 {
                    // Protect against a potential subtract with overflow error since midpoint is a usize
                    // Without the check, this test would panic when we attempted to subtract 1 from 0:
                    // assert!(binary_search(vec![33, 44, 55], 12).is_none());
                    return None;
                }
                upper_bound = midpoint - 1;
            }
            value_at_midpoint if value_at_midpoint == &value => return Some(midpoint),
            _ => (),
        }
    }
    None
}

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

    #[test]
    fn a_empty_vector_returns_none() {
        assert!(binary_search(vec![], 12).is_none());
    }

    #[test]
    fn a_vector_of_length_one_returns_none_if_not_present() {
        assert!(binary_search(vec![33], 12).is_none());
    }

    #[test]
    fn a_vector_of_length_one_returns_the_index_if_present() {
        assert_eq!(binary_search(vec![12], 12).unwrap(), 0);
    }

    #[test]
    fn a_vector_of_length_two_returns_none_if_not_present() {
        assert!(binary_search(vec![33, 44], 12).is_none());
    }

    #[test]
    fn a_vector_of_length_two_returns_the_index_if_present() {
        assert_eq!(binary_search(vec![12, 33], 12).unwrap(), 0);
    }

    #[test]
    fn a_vector_of_length_three_returns_none_if_not_present() {
        assert!(binary_search(vec![33, 44, 55], 12).is_none());
        //assert!(binary_search(vec![1, 2, 3], 12).is_none());
    }

    #[test]
    fn a_vector_of_length_three_returns_the_index_if_present() {
        assert_eq!(binary_search(vec![1, 12, 44], 12).unwrap(), 1);
    }

    #[test]
    fn misc_assertions() {
        assert_eq!(binary_search(vec![12, 33, 55], 12).unwrap(), 0);
        assert_eq!(binary_search(vec![1, 12, 44], 12).unwrap(), 1);
        assert_eq!(binary_search(vec![1, 2, 12], 12).unwrap(), 2);

        assert_eq!(binary_search(vec![1, 2, 12, 22], 12).unwrap(), 2);
        assert_eq!(binary_search(vec![1, 2, 3, 12], 12).unwrap(), 3);
    }
}
<commit_msg>re-enable test assertion<commit_after>pub fn binary_search<T>(vector: Vec<T>, value: T) -> Option<usize>
where
    T: PartialOrd,
{
    if vector.is_empty() {
        return None;
    }

    let mut lower_bound: usize = 0;
    let mut upper_bound = vector.len() - 1;
    while lower_bound <= upper_bound {
        let midpoint = (lower_bound + upper_bound) / 2;
        match &vector[midpoint] {
            value_at_midpoint if value_at_midpoint < &value => lower_bound = midpoint + 1,
            value_at_midpoint if value_at_midpoint > &value => {
                if midpoint == 0 {
                    // Protect against a potential subtract with overflow error since midpoint is a usize
                    // Without the check, this test would panic when we attempted to subtract 1 from 0:
                    // assert!(binary_search(vec![33, 44, 55], 12).is_none());
                    return None;
                }
                upper_bound = midpoint - 1;
            }
            value_at_midpoint if value_at_midpoint == &value => return Some(midpoint),
            _ => (),
        }
    }
    None
}

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

    #[test]
    fn a_empty_vector_returns_none() {
        assert!(binary_search(vec![], 12).is_none());
    }

    #[test]
    fn a_vector_of_length_one_returns_none_if_not_present() {
        assert!(binary_search(vec![33], 12).is_none());
    }

    #[test]
    fn a_vector_of_length_one_returns_the_index_if_present() {
        assert_eq!(binary_search(vec![12], 12).unwrap(), 0);
    }

    #[test]
    fn a_vector_of_length_two_returns_none_if_not_present() {
        assert!(binary_search(vec![33, 44], 12).is_none());
    }

    #[test]
    fn a_vector_of_length_two_returns_the_index_if_present() {
        assert_eq!(binary_search(vec![12, 33], 12).unwrap(), 0);
    }

    #[test]
    fn a_vector_of_length_three_returns_none_if_not_present() {
        assert!(binary_search(vec![33, 44, 55], 12).is_none());
        assert!(binary_search(vec![1, 2, 3], 12).is_none());
    }

    #[test]
    fn a_vector_of_length_three_returns_the_index_if_present() {
        assert_eq!(binary_search(vec![1, 12, 44], 12).unwrap(), 1);
    }

    #[test]
    fn misc_assertions() {
        assert_eq!(binary_search(vec![12, 33, 55], 12).unwrap(), 0);
        assert_eq!(binary_search(vec![1, 12, 44], 12).unwrap(), 1);
        assert_eq!(binary_search(vec![1, 2, 12], 12).unwrap(), 2);

        assert_eq!(binary_search(vec![1, 2, 12, 22], 12).unwrap(), 2);
        assert_eq!(binary_search(vec![1, 2, 3, 12], 12).unwrap(), 3);
    }
}
<|endoftext|>


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

use to_str::{ToStr,ToStrConsume};
use str;
use cast;

#[cfg(test)]
pub struct Ascii { priv chr: u8 }

/// Datatype to hold one ascii character. It is 8 bit long.
#[cfg(notest)]
#[deriving(Clone, Eq, Ord)]
pub struct Ascii { priv chr: u8 }

pub impl Ascii {
    /// Converts a ascii character into a `u8`.
    #[inline(always)]
    fn to_byte(self) -> u8 {
        self.chr
    }

    /// Converts a ascii character into a `char`.
    #[inline(always)]
    fn to_char(self) -> char {
        self.chr as char
    }

    /// Convert to lowercase.
    #[inline(always)]
    fn to_lower(self) -> Ascii {
        if self.chr >= 65 && self.chr <= 90 {
            Ascii{chr: self.chr | 0x20 }
        } else {
            self
        }
    }

    /// Convert to uppercase.
    #[inline(always)]
    fn to_upper(self) -> Ascii {
        if self.chr >= 97 && self.chr <= 122 {
            Ascii{chr: self.chr & !0x20 }
        } else {
            self
        }
    }

    // Compares two ascii characters of equality, ignoring case.
    #[inline(always)]
    fn eq_ignore_case(self, other: Ascii) -> bool {
        self.to_lower().chr == other.to_lower().chr
    }
}

impl ToStr for Ascii {
    #[inline(always)]
    fn to_str(&self) -> ~str { str::from_bytes(['\'' as u8, self.chr, '\'' as u8]) }
}

/// Trait for converting into an ascii type.
pub trait AsciiCast<T> {
    /// Convert to an ascii type
    fn to_ascii(&self) -> T;

    /// Check if convertible to ascii
    fn is_ascii(&self) -> bool;
}

impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] {
    #[inline(always)]
    fn to_ascii(&self) -> &'self[Ascii] {
        assert!(self.is_ascii());

        unsafe{ cast::transmute(*self) }
    }

    #[inline(always)]
    fn is_ascii(&self) -> bool {
        for self.each |b| {
            if !b.is_ascii() { return false; }
        }
        true
    }
}

impl<'self> AsciiCast<&'self[Ascii]> for &'self str {
    #[inline(always)]
    fn to_ascii(&self) -> &'self[Ascii] {
        assert!(self.is_ascii());

        let (p,len): (*u8, uint) = unsafe{ cast::transmute(*self) };
        unsafe{ cast::transmute((p, len - 1))}
    }

    #[inline(always)]
    fn is_ascii(&self) -> bool {
        for self.each |b| {
            if !b.is_ascii() { return false; }
        }
        true
    }
}

impl AsciiCast<Ascii> for u8 {
    #[inline(always)]
    fn to_ascii(&self) -> Ascii {
        assert!(self.is_ascii());
        Ascii{ chr: *self }
    }

    #[inline(always)]
    fn is_ascii(&self) -> bool {
        *self & 128 == 0u8
    }
}

impl AsciiCast<Ascii> for char {

    #[inline(always)]
    fn to_ascii(&self) -> Ascii {
        assert!(self.is_ascii());
        Ascii{ chr: *self as u8 }
    }

    #[inline(always)]
    fn is_ascii(&self) -> bool {
        *self - ('\x7F' & *self) == '\x00'
    }
}

/// Trait for copyless casting to an ascii vector.
pub trait OwnedAsciiCast {
    /// Take ownership and cast to an ascii vector without trailing zero element.
    fn to_ascii_consume(self) -> ~[Ascii];
}

impl OwnedAsciiCast for ~[u8] {
    #[inline(always)]
    fn to_ascii_consume(self) -> ~[Ascii] {
        assert!(self.is_ascii());

        unsafe {cast::transmute(self)}
    }
}

impl OwnedAsciiCast for ~str {
    #[inline(always)]
    fn to_ascii_consume(self) -> ~[Ascii] {
        let mut s = self;
        unsafe {
            str::raw::pop_byte(&mut s);
            cast::transmute(s)
        }
    }
}

/// Trait for converting an ascii type to a string. Needed to convert `&[Ascii]` to `~str`
pub trait ToStrAscii {
    /// Convert to a string.
    fn to_str_ascii(&self) -> ~str;
}

impl<'self> ToStrAscii for &'self [Ascii] {
    #[inline(always)]
    fn to_str_ascii(&self) -> ~str {
        let mut cpy = self.to_owned();
        cpy.push(0u8.to_ascii());
        unsafe {cast::transmute(cpy)}
    }
}

impl ToStrConsume for ~[Ascii] {
    #[inline(always)]
    fn to_str_consume(self) -> ~str {
        let mut cpy = self;
        cpy.push(0u8.to_ascii());
        unsafe {cast::transmute(cpy)}
    }
}

// NOTE: Remove stage0 marker after snapshot
#[cfg(and(test, not(stage0)))]
mod tests {
    use super::*;
    use to_str::{ToStr,ToStrConsume};
    use str;
    use cast;

    macro_rules! v2ascii (
        ( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]);
        (~[$($e:expr),*]) => (~[$(Ascii{chr:$e}),*]);
    )

    #[test]
    fn test_ascii() {
        assert_eq!(65u8.to_ascii().to_byte(), 65u8);
        assert_eq!(65u8.to_ascii().to_char(), 'A');
        assert_eq!('A'.to_ascii().to_char(), 'A');
        assert_eq!('A'.to_ascii().to_byte(), 65u8);

        assert_eq!('A'.to_ascii().to_lower().to_char, 'a');
        assert_eq!('Z'.to_ascii().to_lower().to_char, 'z');
        assert_eq!('a'.to_ascii().to_upper().to_char, 'A');
        assert_eq!('z'.to_ascii().to_upper().to_char, 'Z');

        assert_eq!('@'.to_ascii().to_lower().to_char, '@');
        assert_eq!('['.to_ascii().to_lower().to_char, '[');
        assert_eq!('`'.to_ascii().to_upper().to_char, '`');
        assert_eq!('{'.to_ascii().to_upper().to_char, '{');
    }

    #[test]
    fn test_ascii_vec() {
        assert_eq!((&[40u8, 32u8, 59u8]).to_ascii(), v2ascii!([40, 32, 59]));
        assert_eq!("( ;".to_ascii(),                 v2ascii!([40, 32, 59]));
        // FIXME: #5475 borrowchk error, owned vectors do not live long enough
        // if chained-from directly
        let v = ~[40u8, 32u8, 59u8]; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));
        let v = ~"( ;";              assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));
    }

    #[test]
    fn test_owned_ascii_vec() {
        // FIXME: #4318 Compiler crashes on moving self
        //assert_eq!(~"( ;".to_ascii_consume(), v2ascii!(~[40, 32, 59]));
        //assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume(), v2ascii!(~[40, 32, 59]));
        //assert_eq!(~"( ;".to_ascii_consume_with_null(), v2ascii!(~[40, 32, 59, 0]));
        //assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume_with_null(),
        //           v2ascii!(~[40, 32, 59, 0]));
    }

    #[test]
    fn test_ascii_to_str() { assert_eq!(v2ascii!([40, 32, 59]).to_str_ascii(), ~"( ;"); }

    #[test]
    fn test_ascii_to_str_consume() {
        // FIXME: #4318 Compiler crashes on moving self
        //assert_eq!(v2ascii!(~[40, 32, 59]).to_str_consume(), ~"( ;");
    }

    #[test] #[should_fail]
    fn test_ascii_vec_fail_u8_slice()  { (&[127u8, 128u8, 255u8]).to_ascii(); }

    #[test] #[should_fail]
    fn test_ascii_vec_fail_str_slice() { "zoä华".to_ascii(); }

    #[test] #[should_fail]
    fn test_ascii_fail_u8_slice() { 255u8.to_ascii(); }

    #[test] #[should_fail]
    fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
}

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

use to_str::{ToStr,ToStrConsume};
use str;
use cast;

#[cfg(test)]
pub struct Ascii { priv chr: u8 }

/// Datatype to hold one ascii character. It is 8 bit long.
#[cfg(notest)]
#[deriving(Clone, Eq, Ord)]
pub struct Ascii { priv chr: u8 }

pub impl Ascii {
    /// Converts a ascii character into a `u8`.
    #[inline(always)]
    fn to_byte(self) -> u8 {
        self.chr
    }

    /// Converts a ascii character into a `char`.
    #[inline(always)]
    fn to_char(self) -> char {
        self.chr as char
    }

    /// Convert to lowercase.
    #[inline(always)]
    fn to_lower(self) -> Ascii {
        if self.chr >= 65 && self.chr <= 90 {
            Ascii{chr: self.chr | 0x20 }
        } else {
            self
        }
    }

    /// Convert to uppercase.
    #[inline(always)]
    fn to_upper(self) -> Ascii {
        if self.chr >= 97 && self.chr <= 122 {
            Ascii{chr: self.chr & !0x20 }
        } else {
            self
        }
    }

    // Compares two ascii characters of equality, ignoring case.
    #[inline(always)]
    fn eq_ignore_case(self, other: Ascii) -> bool {
        self.to_lower().chr == other.to_lower().chr
    }
}

impl ToStr for Ascii {
    #[inline(always)]
    fn to_str(&self) -> ~str { str::from_bytes(['\'' as u8, self.chr, '\'' as u8]) }
}

/// Trait for converting into an ascii type.
pub trait AsciiCast<T> {
    /// Convert to an ascii type
    fn to_ascii(&self) -> T;

    /// Check if convertible to ascii
    fn is_ascii(&self) -> bool;
}

impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] {
    #[inline(always)]
    fn to_ascii(&self) -> &'self[Ascii] {
        assert!(self.is_ascii());

        unsafe{ cast::transmute(*self) }
    }

    #[inline(always)]
    fn is_ascii(&self) -> bool {
        for self.each |b| {
            if !b.is_ascii() { return false; }
        }
        true
    }
}

impl<'self> AsciiCast<&'self[Ascii]> for &'self str {
    #[inline(always)]
    fn to_ascii(&self) -> &'self[Ascii] {
        assert!(self.is_ascii());

        let (p,len): (*u8, uint) = unsafe{ cast::transmute(*self) };
        unsafe{ cast::transmute((p, len - 1))}
    }

    #[inline(always)]
    fn is_ascii(&self) -> bool {
        for self.each |b| {
            if !b.is_ascii() { return false; }
        }
        true
    }
}

impl AsciiCast<Ascii> for u8 {
    #[inline(always)]
    fn to_ascii(&self) -> Ascii {
        assert!(self.is_ascii());
        Ascii{ chr: *self }
    }

    #[inline(always)]
    fn is_ascii(&self) -> bool {
        *self & 128 == 0u8
    }
}

impl AsciiCast<Ascii> for char {

    #[inline(always)]
    fn to_ascii(&self) -> Ascii {
        assert!(self.is_ascii());
        Ascii{ chr: *self as u8 }
    }

    #[inline(always)]
    fn is_ascii(&self) -> bool {
        *self - ('\x7F' & *self) == '\x00'
    }
}

/// Trait for copyless casting to an ascii vector.
pub trait OwnedAsciiCast {
    /// Take ownership and cast to an ascii vector without trailing zero element.
    fn to_ascii_consume(self) -> ~[Ascii];
}

impl OwnedAsciiCast for ~[u8] {
    #[inline(always)]
    fn to_ascii_consume(self) -> ~[Ascii] {
        assert!(self.is_ascii());

        unsafe {cast::transmute(self)}
    }
}

impl OwnedAsciiCast for ~str {
    #[inline(always)]
    fn to_ascii_consume(self) -> ~[Ascii] {
        let mut s = self;
        unsafe {
            str::raw::pop_byte(&mut s);
            cast::transmute(s)
        }
    }
}

/// Trait for converting an ascii type to a string. Needed to convert `&[Ascii]` to `~str`
pub trait ToStrAscii {
    /// Convert to a string.
    fn to_str_ascii(&self) -> ~str;
}

impl<'self> ToStrAscii for &'self [Ascii] {
    #[inline(always)]
    fn to_str_ascii(&self) -> ~str {
        let mut cpy = self.to_owned();
        cpy.push(0u8.to_ascii());
        unsafe {cast::transmute(cpy)}
    }
}

impl ToStrConsume for ~[Ascii] {
    #[inline(always)]
    fn to_str_consume(self) -> ~str {
        let mut cpy = self;
        cpy.push(0u8.to_ascii());
        unsafe {cast::transmute(cpy)}
    }
}

// NOTE: Remove stage0 marker after snapshot
#[cfg(and(test, not(stage0)))]
mod tests {
    use super::*;
    use to_str::{ToStr,ToStrConsume};
    use str;
    use cast;

    macro_rules! v2ascii (
        ( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]);
        (~[$($e:expr),*]) => (~[$(Ascii{chr:$e}),*]);
    )

    #[test]
    fn test_ascii() {
        assert_eq!(65u8.to_ascii().to_byte(), 65u8);
        assert_eq!(65u8.to_ascii().to_char(), 'A');
        assert_eq!('A'.to_ascii().to_char(), 'A');
        assert_eq!('A'.to_ascii().to_byte(), 65u8);

        assert_eq!('A'.to_ascii().to_lower().to_char, 'a');
        assert_eq!('Z'.to_ascii().to_lower().to_char, 'z');
        assert_eq!('a'.to_ascii().to_upper().to_char, 'A');
        assert_eq!('z'.to_ascii().to_upper().to_char, 'Z');

        assert_eq!('@'.to_ascii().to_lower().to_char, '@');
        assert_eq!('['.to_ascii().to_lower().to_char, '[');
        assert_eq!('`'.to_ascii().to_upper().to_char, '`');
        assert_eq!('{'.to_ascii().to_upper().to_char, '{');
    }

    #[test]
    fn test_ascii_vec() {
        assert_eq!((&[40u8, 32u8, 59u8]).to_ascii(), v2ascii!([40, 32, 59]));
        assert_eq!("( ;".to_ascii(),                 v2ascii!([40, 32, 59]));
        // FIXME: #5475 borrowchk error, owned vectors do not live long enough
        // if chained-from directly
        let v = ~[40u8, 32u8, 59u8]; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));
        let v = ~"( ;";              assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));
    }

    #[test]
    fn test_owned_ascii_vec() {
        // FIXME: #4318 Compiler crashes on moving self
        //assert_eq!(~"( ;".to_ascii_consume(), v2ascii!(~[40, 32, 59]));
        //assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume(), v2ascii!(~[40, 32, 59]));
        //assert_eq!(~"( ;".to_ascii_consume_with_null(), v2ascii!(~[40, 32, 59, 0]));
        //assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume_with_null(),
        //           v2ascii!(~[40, 32, 59, 0]));
    }

    #[test]
    fn test_ascii_to_str() { assert_eq!(v2ascii!([40, 32, 59]).to_str_ascii(), ~"( ;"); }

    #[test]
    fn test_ascii_to_str_consume() {
        // FIXME: #4318 Compiler crashes on moving self
        //assert_eq!(v2ascii!(~[40, 32, 59]).to_str_consume(), ~"( ;");
    }

    #[test] #[should_fail]
    fn test_ascii_vec_fail_u8_slice()  { (&[127u8, 128u8, 255u8]).to_ascii(); }

    #[test] #[should_fail]
    fn test_ascii_vec_fail_str_slice() { "zoä华".to_ascii(); }

    #[test] #[should_fail]
    fn test_ascii_fail_u8_slice() { 255u8.to_ascii(); }

    #[test] #[should_fail]
    fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
}

<|endoftext|>


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

// This module contains some shared code for encoding and decoding various
// things from the `ty` module, and in particular implements support for
// "shorthands" which allow to have pointers back into the already encoded
// stream instead of re-encoding the same thing twice.
//
// The functionality in here is shared between persisting to crate metadata and
// persisting to incr. comp. caches.

use hir::def_id::{DefId, CrateNum};
use middle::const_val::ByteArray;
use rustc_data_structures::fx::FxHashMap;
use rustc_serialize::{Decodable, Decoder, Encoder, Encodable, opaque};
use std::hash::Hash;
use std::intrinsics;
use ty::{self, Ty, TyCtxt};
use ty::subst::Substs;

/// The shorthand encoding uses an enum's variant index `usize`
/// and is offset by this value so it never matches a real variant.
/// This offset is also chosen so that the first byte is never < 0x80.
pub const SHORTHAND_OFFSET: usize = 0x80;

pub trait EncodableWithShorthand: Clone + Eq + Hash {
    type Variant: Encodable;
    fn variant(&self) -> &Self::Variant;
}

impl<'tcx> EncodableWithShorthand for Ty<'tcx> {
    type Variant = ty::TypeVariants<'tcx>;
    fn variant(&self) -> &Self::Variant {
        &self.sty
    }
}

impl<'tcx> EncodableWithShorthand for ty::Predicate<'tcx> {
    type Variant = ty::Predicate<'tcx>;
    fn variant(&self) -> &Self::Variant {
        self
    }
}

pub trait TyEncoder: Encoder {
    fn position(&self) -> usize;
}

impl<'buf> TyEncoder for opaque::Encoder<'buf> {
    #[inline]
    fn position(&self) -> usize {
        self.position()
    }
}

/// Encode the given value or a previously cached shorthand.
pub fn encode_with_shorthand<E, T, M>(encoder: &mut E,
                                      value: &T,
                                      cache: M)
                                      -> Result<(), E::Error>
    where E: TyEncoder,
          M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>,
          T: EncodableWithShorthand,
{
    let existing_shorthand = cache(encoder).get(value).cloned();
    if let Some(shorthand) = existing_shorthand {
        return encoder.emit_usize(shorthand);
    }

    let variant = value.variant();

    let start = encoder.position();
    variant.encode(encoder)?;
    let len = encoder.position() - start;

    // The shorthand encoding uses the same usize as the
    // discriminant, with an offset so they can't conflict.
    let discriminant = unsafe { intrinsics::discriminant_value(variant) };
    assert!(discriminant < SHORTHAND_OFFSET as u64);
    let shorthand = start + SHORTHAND_OFFSET;

    // Get the number of bits that leb128 could fit
    // in the same space as the fully encoded type.
    let leb128_bits = len * 7;

    // Check that the shorthand is a not longer than the
    // full encoding itself, i.e. it's an obvious win.
    if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
        cache(encoder).insert(value.clone(), shorthand);
    }

    Ok(())
}

pub fn encode_predicates<'tcx, E, C>(encoder: &mut E,
                                     predicates: &ty::GenericPredicates<'tcx>,
                                     cache: C)
                                     -> Result<(), E::Error>
    where E: TyEncoder,
          C: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<ty::Predicate<'tcx>, usize>,
{
    predicates.parent.encode(encoder)?;
    predicates.predicates.len().encode(encoder)?;
    for predicate in &predicates.predicates {
        encode_with_shorthand(encoder, predicate, &cache)?
    }
    Ok(())
}

pub trait TyDecoder<'a, 'tcx: 'a>: Decoder {

    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>;

    fn peek_byte(&self) -> u8;

    fn position(&self) -> usize;

    fn cached_ty_for_shorthand<F>(&mut self,
                                  shorthand: usize,
                                  or_insert_with: F)
                                  -> Result<Ty<'tcx>, Self::Error>
        where F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>;

    fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
        where F: FnOnce(&mut Self) -> R;

    fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum;

    fn positioned_at_shorthand(&self) -> bool {
        (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
    }
}

#[inline]
pub fn decode_cnum<'a, 'tcx, D>(decoder: &mut D) -> Result<CrateNum, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    let cnum = CrateNum::from_u32(u32::decode(decoder)?);
    Ok(decoder.map_encoded_cnum_to_current(cnum))
}

#[inline]
pub fn decode_ty<'a, 'tcx, D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    // Handle shorthands first, if we have an usize > 0x80.
    if decoder.positioned_at_shorthand() {
        let pos = decoder.read_usize()?;
        assert!(pos >= SHORTHAND_OFFSET);
        let shorthand = pos - SHORTHAND_OFFSET;

        decoder.cached_ty_for_shorthand(shorthand, |decoder| {
            decoder.with_position(shorthand, Ty::decode)
        })
    } else {
        let tcx = decoder.tcx();
        Ok(tcx.mk_ty(ty::TypeVariants::decode(decoder)?))
    }
}

#[inline]
pub fn decode_predicates<'a, 'tcx, D>(decoder: &mut D)
                                      -> Result<ty::GenericPredicates<'tcx>, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    Ok(ty::GenericPredicates {
        parent: Decodable::decode(decoder)?,
        predicates: (0..decoder.read_usize()?).map(|_| {
                // Handle shorthands first, if we have an usize > 0x80.
                if decoder.positioned_at_shorthand() {
                    let pos = decoder.read_usize()?;
                    assert!(pos >= SHORTHAND_OFFSET);
                    let shorthand = pos - SHORTHAND_OFFSET;

                    decoder.with_position(shorthand, ty::Predicate::decode)
                } else {
                    ty::Predicate::decode(decoder)
                }
            })
            .collect::<Result<Vec<_>, _>>()?,
    })
}

#[inline]
pub fn decode_substs<'a, 'tcx, D>(decoder: &mut D) -> Result<&'tcx Substs<'tcx>, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    let len = decoder.read_usize()?;
    let tcx = decoder.tcx();
    Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
}

#[inline]
pub fn decode_region<'a, 'tcx, D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?))
}

#[inline]
pub fn decode_ty_slice<'a, 'tcx, D>(decoder: &mut D)
                                    -> Result<&'tcx ty::Slice<Ty<'tcx>>, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    let len = decoder.read_usize()?;
    Ok(decoder.tcx().mk_type_list((0..len).map(|_| Decodable::decode(decoder)))?)
}

#[inline]
pub fn decode_adt_def<'a, 'tcx, D>(decoder: &mut D)
                                   -> Result<&'tcx ty::AdtDef, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    let def_id = DefId::decode(decoder)?;
    Ok(decoder.tcx().adt_def(def_id))
}

#[inline]
pub fn decode_existential_predicate_slice<'a, 'tcx, D>(decoder: &mut D)
    -> Result<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    let len = decoder.read_usize()?;
    Ok(decoder.tcx()
              .mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
}

#[inline]
pub fn decode_byte_array<'a, 'tcx, D>(decoder: &mut D)
                                      -> Result<ByteArray<'tcx>, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    Ok(ByteArray {
        data: decoder.tcx().alloc_byte_array(&Vec::decode(decoder)?)
    })
}

#[inline]
pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
                                 -> Result<&'tcx ty::Const<'tcx>, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
}

#[macro_export]
macro_rules! __impl_decoder_methods {
    ($($name:ident -> $ty:ty;)*) => {
        $(fn $name(&mut self) -> Result<$ty, Self::Error> {
            self.opaque.$name()
        })*
    }
}

#[macro_export]
macro_rules! implement_ty_decoder {
    ($DecoderName:ident <$($typaram:tt),*>) => {
        mod __ty_decoder_impl {
            use super::$DecoderName;
            use $crate::ty;
            use $crate::ty::codec::*;
            use $crate::ty::subst::Substs;
            use $crate::hir::def_id::{CrateNum};
            use $crate::middle::const_val::ByteArray;
            use rustc_serialize::{Decoder, SpecializedDecoder};
            use std::borrow::Cow;

            impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
                type Error = String;

                __impl_decoder_methods! {
                    read_nil -> ();

                    read_u128 -> u128;
                    read_u64 -> u64;
                    read_u32 -> u32;
                    read_u16 -> u16;
                    read_u8 -> u8;
                    read_usize -> usize;

                    read_i128 -> i128;
                    read_i64 -> i64;
                    read_i32 -> i32;
                    read_i16 -> i16;
                    read_i8 -> i8;
                    read_isize -> isize;

                    read_bool -> bool;
                    read_f64 -> f64;
                    read_f32 -> f32;
                    read_char -> char;
                    read_str -> Cow<str>;
                }

                fn error(&mut self, err: &str) -> Self::Error {
                    self.opaque.error(err)
                }
            }

            // FIXME(#36588) These impls are horribly unsound as they allow
            // the caller to pick any lifetime for 'tcx, including 'static,
            // by using the unspecialized proxies to them.

            impl<$($typaram),*> SpecializedDecoder<CrateNum> for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
                    decode_cnum(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<ty::Ty<'tcx>> for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self) -> Result<ty::Ty<'tcx>, Self::Error> {
                    decode_ty(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<ty::GenericPredicates<'tcx>>
            for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self) -> Result<ty::GenericPredicates<'tcx>, Self::Error> {
                    decode_predicates(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<&'tcx Substs<'tcx>> for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> {
                    decode_substs(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<ty::Region<'tcx>> for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
                    decode_region(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<&'tcx ty::Slice<ty::Ty<'tcx>>>
            for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self) -> Result<&'tcx ty::Slice<ty::Ty<'tcx>>, Self::Error> {
                    decode_ty_slice(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<&'tcx ty::AdtDef> for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
                    decode_adt_def(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>
                for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self)
                    -> Result<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, Self::Error> {
                    decode_existential_predicate_slice(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<ByteArray<'tcx>> for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self) -> Result<ByteArray<'tcx>, Self::Error> {
                    decode_byte_array(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>>
            for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
                    decode_const(self)
                }
            }
        }
    }
}

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

// This module contains some shared code for encoding and decoding various
// things from the `ty` module, and in particular implements support for
// "shorthands" which allow to have pointers back into the already encoded
// stream instead of re-encoding the same thing twice.
//
// The functionality in here is shared between persisting to crate metadata and
// persisting to incr. comp. caches.

use hir::def_id::{DefId, CrateNum};
use middle::const_val::ByteArray;
use rustc_data_structures::fx::FxHashMap;
use rustc_serialize::{Decodable, Decoder, Encoder, Encodable, opaque};
use std::hash::Hash;
use std::intrinsics;
use ty::{self, Ty, TyCtxt};
use ty::subst::Substs;

/// The shorthand encoding uses an enum's variant index `usize`
/// and is offset by this value so it never matches a real variant.
/// This offset is also chosen so that the first byte is never < 0x80.
pub const SHORTHAND_OFFSET: usize = 0x80;

pub trait EncodableWithShorthand: Clone + Eq + Hash {
    type Variant: Encodable;
    fn variant(&self) -> &Self::Variant;
}

impl<'tcx> EncodableWithShorthand for Ty<'tcx> {
    type Variant = ty::TypeVariants<'tcx>;
    fn variant(&self) -> &Self::Variant {
        &self.sty
    }
}

impl<'tcx> EncodableWithShorthand for ty::Predicate<'tcx> {
    type Variant = ty::Predicate<'tcx>;
    fn variant(&self) -> &Self::Variant {
        self
    }
}

pub trait TyEncoder: Encoder {
    fn position(&self) -> usize;
}

impl<'buf> TyEncoder for opaque::Encoder<'buf> {
    #[inline]
    fn position(&self) -> usize {
        self.position()
    }
}

/// Encode the given value or a previously cached shorthand.
pub fn encode_with_shorthand<E, T, M>(encoder: &mut E,
                                      value: &T,
                                      cache: M)
                                      -> Result<(), E::Error>
    where E: TyEncoder,
          M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>,
          T: EncodableWithShorthand,
{
    let existing_shorthand = cache(encoder).get(value).cloned();
    if let Some(shorthand) = existing_shorthand {
        return encoder.emit_usize(shorthand);
    }

    let variant = value.variant();

    let start = encoder.position();
    variant.encode(encoder)?;
    let len = encoder.position() - start;

    // The shorthand encoding uses the same usize as the
    // discriminant, with an offset so they can't conflict.
    let discriminant = unsafe { intrinsics::discriminant_value(variant) };
    assert!(discriminant < SHORTHAND_OFFSET as u64);
    let shorthand = start + SHORTHAND_OFFSET;

    // Get the number of bits that leb128 could fit
    // in the same space as the fully encoded type.
    let leb128_bits = len * 7;

    // Check that the shorthand is a not longer than the
    // full encoding itself, i.e. it's an obvious win.
    if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
        cache(encoder).insert(value.clone(), shorthand);
    }

    Ok(())
}

pub fn encode_predicates<'tcx, E, C>(encoder: &mut E,
                                     predicates: &ty::GenericPredicates<'tcx>,
                                     cache: C)
                                     -> Result<(), E::Error>
    where E: TyEncoder,
          C: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<ty::Predicate<'tcx>, usize>,
{
    predicates.parent.encode(encoder)?;
    predicates.predicates.len().encode(encoder)?;
    for predicate in &predicates.predicates {
        encode_with_shorthand(encoder, predicate, &cache)?
    }
    Ok(())
}

pub trait TyDecoder<'a, 'tcx: 'a>: Decoder {

    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>;

    fn peek_byte(&self) -> u8;

    fn position(&self) -> usize;

    fn cached_ty_for_shorthand<F>(&mut self,
                                  shorthand: usize,
                                  or_insert_with: F)
                                  -> Result<Ty<'tcx>, Self::Error>
        where F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>;

    fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
        where F: FnOnce(&mut Self) -> R;

    fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum;

    fn positioned_at_shorthand(&self) -> bool {
        (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
    }
}

#[inline]
pub fn decode_cnum<'a, 'tcx, D>(decoder: &mut D) -> Result<CrateNum, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    let cnum = CrateNum::from_u32(u32::decode(decoder)?);
    Ok(decoder.map_encoded_cnum_to_current(cnum))
}

#[inline]
pub fn decode_ty<'a, 'tcx, D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    // Handle shorthands first, if we have an usize > 0x80.
    if decoder.positioned_at_shorthand() {
        let pos = decoder.read_usize()?;
        assert!(pos >= SHORTHAND_OFFSET);
        let shorthand = pos - SHORTHAND_OFFSET;

        decoder.cached_ty_for_shorthand(shorthand, |decoder| {
            decoder.with_position(shorthand, Ty::decode)
        })
    } else {
        let tcx = decoder.tcx();
        Ok(tcx.mk_ty(ty::TypeVariants::decode(decoder)?))
    }
}

#[inline]
pub fn decode_predicates<'a, 'tcx, D>(decoder: &mut D)
                                      -> Result<ty::GenericPredicates<'tcx>, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    Ok(ty::GenericPredicates {
        parent: Decodable::decode(decoder)?,
        predicates: (0..decoder.read_usize()?).map(|_| {
                // Handle shorthands first, if we have an usize > 0x80.
                if decoder.positioned_at_shorthand() {
                    let pos = decoder.read_usize()?;
                    assert!(pos >= SHORTHAND_OFFSET);
                    let shorthand = pos - SHORTHAND_OFFSET;

                    decoder.with_position(shorthand, ty::Predicate::decode)
                } else {
                    ty::Predicate::decode(decoder)
                }
            })
            .collect::<Result<Vec<_>, _>>()?,
    })
}

#[inline]
pub fn decode_substs<'a, 'tcx, D>(decoder: &mut D) -> Result<&'tcx Substs<'tcx>, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    let len = decoder.read_usize()?;
    let tcx = decoder.tcx();
    Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
}

#[inline]
pub fn decode_region<'a, 'tcx, D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?))
}

#[inline]
pub fn decode_ty_slice<'a, 'tcx, D>(decoder: &mut D)
                                    -> Result<&'tcx ty::Slice<Ty<'tcx>>, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    let len = decoder.read_usize()?;
    Ok(decoder.tcx().mk_type_list((0..len).map(|_| Decodable::decode(decoder)))?)
}

#[inline]
pub fn decode_adt_def<'a, 'tcx, D>(decoder: &mut D)
                                   -> Result<&'tcx ty::AdtDef, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    let def_id = DefId::decode(decoder)?;
    Ok(decoder.tcx().adt_def(def_id))
}

#[inline]
pub fn decode_existential_predicate_slice<'a, 'tcx, D>(decoder: &mut D)
    -> Result<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    let len = decoder.read_usize()?;
    Ok(decoder.tcx()
              .mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
}

#[inline]
pub fn decode_byte_array<'a, 'tcx, D>(decoder: &mut D)
                                      -> Result<ByteArray<'tcx>, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    Ok(ByteArray {
        data: decoder.tcx().alloc_byte_array(&Vec::decode(decoder)?)
    })
}

#[inline]
pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
                                 -> Result<&'tcx ty::Const<'tcx>, D::Error>
    where D: TyDecoder<'a, 'tcx>,
          'tcx: 'a,
{
    Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
}

#[macro_export]
macro_rules! __impl_decoder_methods {
    ($($name:ident -> $ty:ty;)*) => {
        $(fn $name(&mut self) -> Result<$ty, Self::Error> {
            self.opaque.$name()
        })*
    }
}

#[macro_export]
macro_rules! implement_ty_decoder {
    ($DecoderName:ident <$($typaram:tt),*>) => {
        mod __ty_decoder_impl {
            use super::$DecoderName;
            use $crate::ty;
            use $crate::ty::codec::*;
            use $crate::ty::subst::Substs;
            use $crate::hir::def_id::{CrateNum};
            use $crate::middle::const_val::ByteArray;
            use rustc_serialize::{Decoder, SpecializedDecoder};
            use std::borrow::Cow;

            impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
                type Error = String;

                __impl_decoder_methods! {
                    read_nil -> ();

                    read_u128 -> u128;
                    read_u64 -> u64;
                    read_u32 -> u32;
                    read_u16 -> u16;
                    read_u8 -> u8;
                    read_usize -> usize;

                    read_i128 -> i128;
                    read_i64 -> i64;
                    read_i32 -> i32;
                    read_i16 -> i16;
                    read_i8 -> i8;
                    read_isize -> isize;

                    read_bool -> bool;
                    read_f64 -> f64;
                    read_f32 -> f32;
                    read_char -> char;
                    read_str -> Cow<str>;
                }

                fn error(&mut self, err: &str) -> Self::Error {
                    self.opaque.error(err)
                }
            }

            // FIXME(#36588) These impls are horribly unsound as they allow
            // the caller to pick any lifetime for 'tcx, including 'static,
            // by using the unspecialized proxies to them.

            impl<$($typaram),*> SpecializedDecoder<CrateNum>
            for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
                    decode_cnum(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<ty::Ty<'tcx>>
            for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self) -> Result<ty::Ty<'tcx>, Self::Error> {
                    decode_ty(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<ty::GenericPredicates<'tcx>>
            for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self)
                                      -> Result<ty::GenericPredicates<'tcx>, Self::Error> {
                    decode_predicates(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<&'tcx Substs<'tcx>>
            for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> {
                    decode_substs(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<ty::Region<'tcx>>
            for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
                    decode_region(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<&'tcx ty::Slice<ty::Ty<'tcx>>>
            for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self)
                                      -> Result<&'tcx ty::Slice<ty::Ty<'tcx>>, Self::Error> {
                    decode_ty_slice(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<&'tcx ty::AdtDef>
            for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
                    decode_adt_def(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>
                for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self)
                    -> Result<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, Self::Error> {
                    decode_existential_predicate_slice(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<ByteArray<'tcx>>
            for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self) -> Result<ByteArray<'tcx>, Self::Error> {
                    decode_byte_array(self)
                }
            }

            impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>>
            for $DecoderName<$($typaram),*> {
                fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
                    decode_const(self)
                }
            }
        }
    }
}

<|endoftext|>


<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
#![allow(
    clippy::unused_unit,
    clippy::needless_return,
    clippy::never_loop,
    clippy::option_map_unit_fn
)]
use super::osm_utils::get_way_coord;
use super::OsmPbfReader;
use crate::admin_geofinder::AdminGeoFinder;
use crate::{labels, settings, utils, Error};
use cosmogony::ZoneType;
use failure::ResultExt;
use osmpbfreader::{OsmId, StoreObjs};
use slog_scope::info;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::ops::Deref;
use std::sync::Arc;

use super::osm_store::{Getter, ObjWrapper};

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[allow(dead_code)]
pub enum Kind {
    Node = 0,
    Way = 1,
    Relation = 2,
}

pub fn streets(
    pbf: &mut OsmPbfReader,
    admins_geofinder: &AdminGeoFinder,
    settings: &settings::osm2mimir::Settings,
) -> Result<Vec<mimir::Street>, Error> {
    let invalid_highways = settings
        .street
        .as_ref()
        .and_then(|street| street.exclusion.highway.as_deref())
        .unwrap_or(&[]);

    let is_valid_highway = |tag: &str| -> bool { !invalid_highways.iter().any(|k| k == tag) };

    let invalid_public_transports = settings
        .street
        .as_ref()
        .and_then(|street| street.exclusion.public_transport.as_deref())
        .unwrap_or(&[]);

    let is_valid_public_transport =
        |tag: &str| -> bool { !invalid_public_transports.iter().any(|k| k == tag) };

    // For the object to be a valid street, it needs to be an osm highway of a valid type,
    // or a relation of type associatedStreet.
    let is_valid_obj = |obj: &osmpbfreader::OsmObj| -> bool {
        match *obj {
            osmpbfreader::OsmObj::Way(ref way) => {
                let has_valid_highway_tag = way
                    .tags
                    .get("highway")
                    .map_or(false, |v| !v.is_empty() && is_valid_highway(v));
                let has_no_excluded_public_transport_tag = way
                    .tags
                    .get("public_transport")
                    .map_or(true, |v| is_valid_public_transport(v));
                let has_valid_name_tag = way.tags.get("name").map_or(false, |v| !v.is_empty());
                has_valid_name_tag
                    && (has_valid_highway_tag || has_no_excluded_public_transport_tag)
            }
            osmpbfreader::OsmObj::Relation(ref rel) => rel
                .tags
                .get("type")
                .map_or(false, |v| v == "associatedStreet"),
            _ => false,
        }
    };

    info!("reading pbf...");
    #[cfg(feature = "db-storage")]
    let mut objs_map = ObjWrapper::new(&settings.database)?;
    #[cfg(not(feature = "db-storage"))]
    let mut objs_map = ObjWrapper::new()?;

    pbf.get_objs_and_deps_store(is_valid_obj, &mut objs_map)
        .context("Error occurred when reading pbf")?;
    info!("reading pbf done.");

    // Builder for street object
    let build_street =
        |id: String, name: String, coord: mimir::Coord, admins: Vec<Arc<mimir::Admin>>| {
            let admins_iter = admins.iter().map(Deref::deref);
            let country_codes = utils::find_country_codes(admins_iter.clone());
            mimir::Street {
                id,
                label: labels::format_street_label(&name, admins_iter, &country_codes),
                name,
                weight: 0.,
                zip_codes: utils::get_zip_codes_from_admins(&admins),
                administrative_regions: admins,
                coord,
                approx_coord: Some(coord.into()),
                distance: None,
                country_codes,
                context: None,
            }
        };

    // Return an iterator giving documents that will be inserted for a given
    // street: one for each hierarchy of admins.
    let build_streets_for_admins =
        move |name: String, id, kind, mut all_admins: Vec<Vec<_>>, coord| {
            let single_output = all_admins.len() <= 1;
            all_admins.sort_unstable(); // sort admins to make id deterministic
            all_admins.into_iter().enumerate().map(move |(i, admins)| {
                let doc_id = {
                    if single_output {
                        format!("street:osm:{}:{}", kind, id)
                    } else {
                        format!("street:osm:{}:{}-{}", kind, id, i)
                    }
                };

                build_street(doc_id, name.clone(), coord, admins)
            })
        };

    // List of outputed streets
    let mut street_list = Vec::new();

    // Sometimes, streets can be divided into several "way"s that still have the same street name.
    // The reason why a street is divided may be that a part of the street become
    // a bridge/tunnel/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 autocompletion, we should tag
    // the osm ways in the relation not to index them twice.
    let mut street_in_relation = HashSet::new();

    objs_map.for_each_filter(Kind::Relation, |obj| {
        let rel = obj.relation().expect("invalid relation filter");
        let rel_name = rel.tags.get("name");

        // Add osmid of all the relation members in the set.
        // Then, we won't create any street for the ways that belong to this relation.

        street_in_relation.extend(
            rel.refs
                .iter()
                .map(|ref_obj| ref_obj.member)
                .filter(OsmId::is_way),
        );

        let rel_street = rel
            .refs
            .iter()
            .filter(|ref_obj| ref_obj.member.is_way() && &ref_obj.role == "street")
            .filter_map(|ref_obj| {
                let obj = objs_map.get(&ref_obj.member)?;
                let way = obj.way()?;
                let coord = get_way_coord(&objs_map, &way);
                let name = rel_name.or_else(|| way.tags.get("name"))?;

                Some(build_streets_for_admins(
                    name.to_string(),
                    rel.id.0,
                    "relation",
                    get_street_admin(admins_geofinder, &objs_map, &way),
                    coord,
                ))
            })
            .next();

        if let Some(street) = rel_street {
            street_list.extend(street);
        }
    });

    // We merge all the ways with same `way_name` and `admin list of level(=city_level)`
    // We use a Map to keep track of the way of smallest Id for a given pair of "name + cities list"
    let mut name_admin_map = BTreeMap::new();

    objs_map.for_each_filter(Kind::Way, |obj| {
        let osmid = obj.id();
        let way = obj.way().expect("invalid way filter");

        if street_in_relation.contains(&osmid) {
            return;
        }

        if let Some(name) = way.tags.get("name") {
            for admins in get_street_admin(admins_geofinder, &objs_map, way) {
                // Discriminate ways with same names by city
                if let Some(city) = admins
                    .iter()
                    .find(|admin| admin.is_city())
                    .map(|city| city.id.to_string())
                {
                    name_admin_map
                        .entry((name.to_string(), city))
                        .and_modify(|(stored_id, stored_admins)| {
                            if *stored_id > osmid {
                                *stored_id = std::cmp::min(*stored_id, osmid);
                                *stored_admins = admins.clone();
                            }
                        })
                        .or_insert((osmid, admins));
                }
            }
        }
    });

    // For each street, construct the list of admins it will be added in.
    // This step ensure that documents have distinguishable IDs if they are
    // added for the same street but different admins.
    let mut all_admins_for_street = HashMap::new();

    for (_, (min_id, admins)) in name_admin_map {
        all_admins_for_street
            .entry(min_id)
            .or_insert_with(Vec::new)
            .push(admins);
    }

    street_list.extend(
        all_admins_for_street
            .into_iter()
            .filter_map(|(id, all_admins)| {
                let obj = objs_map.get(&id)?;
                let way = obj.way()?;

                Some(build_streets_for_admins(
                    way.tags.get("name")?.to_string(),
                    way.id.0,
                    "way",
                    all_admins,
                    get_way_coord(&objs_map, way),
                ))
            })
            .flatten(),
    );

    Ok(street_list)
}

/// Returns branches of admins encompassing the street `way`.
fn get_street_admin<T: StoreObjs + Getter>(
    admins_geofinder: &AdminGeoFinder,
    obj_map: &T,
    way: &osmpbfreader::objects::Way,
) -> Vec<Vec<Arc<mimir::Admin>>> {
    let nb_nodes = way.nodes.len();

    // To avoid corner cases where the ends of the way are near
    // administrative boundaries, the geofinder is called
    // preferably on a middle node.
    let (nodes_left, nodes_right) = (
        way.nodes[..nb_nodes / 2].iter(),
        way.nodes[nb_nodes / 2..].iter(),
    );

    nodes_right
        .chain(nodes_left)
        .filter_map(|node_id| obj_map.get(&(*node_id).into()))
        .filter_map(|node_obj| {
            node_obj.node().map(|node| geo_types::Coordinate {
                x: node.lon(),
                y: node.lat(),
            })
        })
        .next()
        .map_or_else(Vec::new, |coord| {
            // If the coords are part of several cities or suburbs, they are
            // all part of the output together with their parents. For
            // performance reasons, if the admin hierarchy is built of zones
            // bigger than cities, at most one result will belong to the output.
            admins_geofinder.get_admins_if(&coord, |admin| {
                admin
                    .zone_type
                    .map(|zt| zt <= ZoneType::City)
                    .unwrap_or(false)
            })
        })
}

pub fn compute_street_weight(streets: &mut Vec<mimir::Street>) {
    for st in streets {
        for admin in &mut st.administrative_regions {
            if admin.is_city() {
                st.weight = admin.weight;
                break;
            }
        }
    }
}
<commit_msg>[Fixed] Invalid handling of no public_transport<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
#![allow(
    clippy::unused_unit,
    clippy::needless_return,
    clippy::never_loop,
    clippy::option_map_unit_fn
)]
use super::osm_utils::get_way_coord;
use super::OsmPbfReader;
use crate::admin_geofinder::AdminGeoFinder;
use crate::{labels, settings, utils, Error};
use cosmogony::ZoneType;
use failure::ResultExt;
use osmpbfreader::{OsmId, StoreObjs};
use slog_scope::info;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::ops::Deref;
use std::sync::Arc;

use super::osm_store::{Getter, ObjWrapper};

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[allow(dead_code)]
pub enum Kind {
    Node = 0,
    Way = 1,
    Relation = 2,
}

pub fn streets(
    pbf: &mut OsmPbfReader,
    admins_geofinder: &AdminGeoFinder,
    settings: &settings::osm2mimir::Settings,
) -> Result<Vec<mimir::Street>, Error> {
    let invalid_highways = settings
        .street
        .as_ref()
        .and_then(|street| street.exclusion.highway.as_deref())
        .unwrap_or(&[]);

    let is_valid_highway = |tag: &str| -> bool { !invalid_highways.iter().any(|k| k == tag) };

    let invalid_public_transports = settings
        .street
        .as_ref()
        .and_then(|street| street.exclusion.public_transport.as_deref())
        .unwrap_or(&[]);

    let is_valid_public_transport =
        |tag: &str| -> bool { !invalid_public_transports.iter().any(|k| k == tag) };

    // For the object to be a valid street, it needs to be an osm highway of a valid type,
    // or a relation of type associatedStreet.
    let is_valid_obj = |obj: &osmpbfreader::OsmObj| -> bool {
        match *obj {
            osmpbfreader::OsmObj::Way(ref way) => {
                let has_valid_highway_tag = way
                    .tags
                    .get("highway")
                    .map_or(false, |v| !v.is_empty() && is_valid_highway(v));
                let has_no_excluded_public_transport_tag = way
                    .tags
                    .get("public_transport")
                    .map_or(true, |v| is_valid_public_transport(v));
                let has_valid_name_tag = way.tags.get("name").map_or(false, |v| !v.is_empty());
                has_valid_name_tag && has_valid_highway_tag && has_no_excluded_public_transport_tag
            }
            osmpbfreader::OsmObj::Relation(ref rel) => rel
                .tags
                .get("type")
                .map_or(false, |v| v == "associatedStreet"),
            _ => false,
        }
    };

    info!("reading pbf...");
    #[cfg(feature = "db-storage")]
    let mut objs_map = ObjWrapper::new(&settings.database)?;
    #[cfg(not(feature = "db-storage"))]
    let mut objs_map = ObjWrapper::new()?;

    pbf.get_objs_and_deps_store(is_valid_obj, &mut objs_map)
        .context("Error occurred when reading pbf")?;
    info!("reading pbf done.");

    // Builder for street object
    let build_street =
        |id: String, name: String, coord: mimir::Coord, admins: Vec<Arc<mimir::Admin>>| {
            let admins_iter = admins.iter().map(Deref::deref);
            let country_codes = utils::find_country_codes(admins_iter.clone());
            mimir::Street {
                id,
                label: labels::format_street_label(&name, admins_iter, &country_codes),
                name,
                weight: 0.,
                zip_codes: utils::get_zip_codes_from_admins(&admins),
                administrative_regions: admins,
                coord,
                approx_coord: Some(coord.into()),
                distance: None,
                country_codes,
                context: None,
            }
        };

    // Return an iterator giving documents that will be inserted for a given
    // street: one for each hierarchy of admins.
    let build_streets_for_admins =
        move |name: String, id, kind, mut all_admins: Vec<Vec<_>>, coord| {
            let single_output = all_admins.len() <= 1;
            all_admins.sort_unstable(); // sort admins to make id deterministic
            all_admins.into_iter().enumerate().map(move |(i, admins)| {
                let doc_id = {
                    if single_output {
                        format!("street:osm:{}:{}", kind, id)
                    } else {
                        format!("street:osm:{}:{}-{}", kind, id, i)
                    }
                };

                build_street(doc_id, name.clone(), coord, admins)
            })
        };

    // List of outputed streets
    let mut street_list = Vec::new();

    // Sometimes, streets can be divided into several "way"s that still have the same street name.
    // The reason why a street is divided may be that a part of the street become
    // a bridge/tunnel/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 autocompletion, we should tag
    // the osm ways in the relation not to index them twice.
    let mut street_in_relation = HashSet::new();

    objs_map.for_each_filter(Kind::Relation, |obj| {
        let rel = obj.relation().expect("invalid relation filter");
        let rel_name = rel.tags.get("name");

        // Add osmid of all the relation members in the set.
        // Then, we won't create any street for the ways that belong to this relation.

        street_in_relation.extend(
            rel.refs
                .iter()
                .map(|ref_obj| ref_obj.member)
                .filter(OsmId::is_way),
        );

        let rel_street = rel
            .refs
            .iter()
            .filter(|ref_obj| ref_obj.member.is_way() && &ref_obj.role == "street")
            .filter_map(|ref_obj| {
                let obj = objs_map.get(&ref_obj.member)?;
                let way = obj.way()?;
                let coord = get_way_coord(&objs_map, &way);
                let name = rel_name.or_else(|| way.tags.get("name"))?;

                Some(build_streets_for_admins(
                    name.to_string(),
                    rel.id.0,
                    "relation",
                    get_street_admin(admins_geofinder, &objs_map, &way),
                    coord,
                ))
            })
            .next();

        if let Some(street) = rel_street {
            street_list.extend(street);
        }
    });

    // We merge all the ways with same `way_name` and `admin list of level(=city_level)`
    // We use a Map to keep track of the way of smallest Id for a given pair of "name + cities list"
    let mut name_admin_map = BTreeMap::new();

    objs_map.for_each_filter(Kind::Way, |obj| {
        let osmid = obj.id();
        let way = obj.way().expect("invalid way filter");

        if street_in_relation.contains(&osmid) {
            return;
        }

        if let Some(name) = way.tags.get("name") {
            for admins in get_street_admin(admins_geofinder, &objs_map, way) {
                // Discriminate ways with same names by city
                if let Some(city) = admins
                    .iter()
                    .find(|admin| admin.is_city())
                    .map(|city| city.id.to_string())
                {
                    name_admin_map
                        .entry((name.to_string(), city))
                        .and_modify(|(stored_id, stored_admins)| {
                            if *stored_id > osmid {
                                *stored_id = std::cmp::min(*stored_id, osmid);
                                *stored_admins = admins.clone();
                            }
                        })
                        .or_insert((osmid, admins));
                }
            }
        }
    });

    // For each street, construct the list of admins it will be added in.
    // This step ensure that documents have distinguishable IDs if they are
    // added for the same street but different admins.
    let mut all_admins_for_street = HashMap::new();

    for (_, (min_id, admins)) in name_admin_map {
        all_admins_for_street
            .entry(min_id)
            .or_insert_with(Vec::new)
            .push(admins);
    }

    street_list.extend(
        all_admins_for_street
            .into_iter()
            .filter_map(|(id, all_admins)| {
                let obj = objs_map.get(&id)?;
                let way = obj.way()?;

                Some(build_streets_for_admins(
                    way.tags.get("name")?.to_string(),
                    way.id.0,
                    "way",
                    all_admins,
                    get_way_coord(&objs_map, way),
                ))
            })
            .flatten(),
    );

    Ok(street_list)
}

/// Returns branches of admins encompassing the street `way`.
fn get_street_admin<T: StoreObjs + Getter>(
    admins_geofinder: &AdminGeoFinder,
    obj_map: &T,
    way: &osmpbfreader::objects::Way,
) -> Vec<Vec<Arc<mimir::Admin>>> {
    let nb_nodes = way.nodes.len();

    // To avoid corner cases where the ends of the way are near
    // administrative boundaries, the geofinder is called
    // preferably on a middle node.
    let (nodes_left, nodes_right) = (
        way.nodes[..nb_nodes / 2].iter(),
        way.nodes[nb_nodes / 2..].iter(),
    );

    nodes_right
        .chain(nodes_left)
        .filter_map(|node_id| obj_map.get(&(*node_id).into()))
        .filter_map(|node_obj| {
            node_obj.node().map(|node| geo_types::Coordinate {
                x: node.lon(),
                y: node.lat(),
            })
        })
        .next()
        .map_or_else(Vec::new, |coord| {
            // If the coords are part of several cities or suburbs, they are
            // all part of the output together with their parents. For
            // performance reasons, if the admin hierarchy is built of zones
            // bigger than cities, at most one result will belong to the output.
            admins_geofinder.get_admins_if(&coord, |admin| {
                admin
                    .zone_type
                    .map(|zt| zt <= ZoneType::City)
                    .unwrap_or(false)
            })
        })
}

pub fn compute_street_weight(streets: &mut Vec<mimir::Street>) {
    for st in streets {
        for admin in &mut st.administrative_regions {
            if admin.is_city() {
                st.weight = admin.weight;
                break;
            }
        }
    }
}
<|endoftext|>