<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/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::EventSourceBinding::{EventSourceInit, EventSourceMethods, Wrap};
use dom::bindings::error::{Error, Fallible};
use dom::bindings::js::Root;
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
use dom::eventtarget::EventTarget;
use dom::globalscope::GlobalScope;
use hyper::header::{Accept, qitem};
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use net_traits::{CoreResourceMsg, FetchMetadata, FetchResponseListener, NetworkError};
use net_traits::request::{CacheMode, CorsSettings, CredentialsMode};
use net_traits::request::{RequestInit, RequestMode};
use network_listener::{NetworkListener, PreInvoke};
use std::cell::Cell;
use std::sync::{Arc, Mutex};
use url::Url;

#[derive(JSTraceable, PartialEq, Copy, Clone, Debug, HeapSizeOf)]
/// https://html.spec.whatwg.org/multipage/#dom-eventsource-readystate
enum ReadyState {
    Connecting = 0,
    #[allow(dead_code)]
    Open = 1,
    Closed = 2
}

#[dom_struct]
pub struct EventSource {
    eventtarget: EventTarget,
    url: DOMRefCell<Option<Url>>,
    request: DOMRefCell<Option<RequestInit>>,
    ready_state: Cell<EventSourceReadyState>,
    with_credentials: bool,
    last_event_id: DOMRefCell<DOMString>
}

struct EventSourceContext;

impl FetchResponseListener for EventSourceContext {
    fn process_request_body(&mut self) {
        // TODO
    }

    fn process_request_eof(&mut self) {
        // TODO
    }

    fn process_response(&mut self, _metadata: Result<FetchMetadata, NetworkError>) {
        // TODO
    }

    fn process_response_chunk(&mut self, mut _chunk: Vec<u8>) {
        // TODO
    }

    fn process_response_eof(&mut self, _response: Result<(), NetworkError>) {
        // TODO
    }
}

impl PreInvoke for EventSourceContext {}

impl EventSource {
    fn new_inherited(with_credentials: bool) -> EventSource {
        EventSource {
            eventtarget: EventTarget::new_inherited(),
            url: DOMRefCell::new(None),
            request: DOMRefCell::new(None),
            ready_state: Cell::new(ReadyState::Connecting),
            with_credentials: with_credentials,
            last_event_id: DOMRefCell::new(DOMString::from(""))
        }
    }

    fn new(global: &GlobalScope, with_credentials: bool) -> Root<EventSource> {
        reflect_dom_object(box EventSource::new_inherited(with_credentials),
                           global,
                           Wrap)
    }

    pub fn Constructor(global: &GlobalScope,
                       url: DOMString,
                       event_source_init: &EventSourceInit) -> Fallible<Root<EventSource>> {
        // Step 1
        let ev = EventSource::new(global, event_source_init.withCredentials);
        // TODO: Step 2 relevant settings object
        // Step 3
        let base_url = global.api_base_url();
        let url_record = match base_url.join(&*url) {
            Ok(u) => u,
            //  Step 4
            Err(_) => return Err(Error::Syntax)
        };
        // Step 5
        *ev.url.borrow_mut() = Some(url_record.clone());
        // Steps 6-7
        let cors_attribute_state = if event_source_init.withCredentials {
            CorsSettings::UseCredentials
        } else {
            CorsSettings::Anonymous
        };
        // Step 8
        // TODO: Step 9 set request's client settings
        let mut request = RequestInit {
            url: url_record,
            origin: global.get_url(),
            pipeline_id: Some(global.pipeline_id()),
            // https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request
            use_url_credentials: true,
            mode: RequestMode::CorsMode,
            credentials_mode: if cors_attribute_state == CorsSettings::Anonymous {
                CredentialsMode::CredentialsSameOrigin
            } else {
                CredentialsMode::Include
            },
            ..RequestInit::default()
        };
        // Step 10
        request.headers.set(Accept(vec![qitem(mime!(Text / EventStream))]));
        // Step 11
        request.cache_mode = CacheMode::NoStore;
        // Step 12
        *ev.request.borrow_mut() = Some(request.clone());
        // Step 14
        let context = EventSourceContext;
        let listener = NetworkListener {
            context: Arc::new(Mutex::new(context)),
            task_source: global.networking_task_source(),
            wrapper: Some(global.get_runnable_wrapper())
        };
        let (action_sender, action_receiver) = ipc::channel().unwrap();
        ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
            listener.notify_fetch(message.to().unwrap());
        });
        global.core_resource_thread().send(CoreResourceMsg::Fetch(request, action_sender)).unwrap();
        // Step 13
        Ok(ev)
    }
}

impl EventSourceMethods for EventSource {
    // https://html.spec.whatwg.org/multipage/#handler-eventsource-onopen
    event_handler!(open, GetOnopen, SetOnopen);

    // https://html.spec.whatwg.org/multipage/#handler-eventsource-onmessage
    event_handler!(message, GetOnmessage, SetOnmessage);

    // https://html.spec.whatwg.org/multipage/#handler-eventsource-onerror
    event_handler!(error, GetOnerror, SetOnerror);

    // https://html.spec.whatwg.org/multipage/#dom-eventsource-url
    fn Url(&self) -> DOMString {
        DOMString::from(self.url.borrow().clone().map_or("".to_owned(), Url::into_string))
    }

    // https://html.spec.whatwg.org/multipage/#dom-eventsource-withcredentials
    fn WithCredentials(&self) -> bool {
        self.with_credentials
    }

    // https://html.spec.whatwg.org/multipage/#dom-eventsource-readystate
    fn ReadyState(&self) -> u16 {
        self.ready_state.get() as u16
    }

    // https://html.spec.whatwg.org/multipage/#dom-eventsource-close
    fn Close(&self) {
        self.ready_state.set(ReadyState::Closed);
        // TODO: Terminate ongoing fetch
    }
}
<commit_msg>Parse metadata in EventSource<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/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::EventSourceBinding::{EventSourceInit, EventSourceMethods, Wrap};
use dom::bindings::error::{Error, Fallible};
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
use dom::eventtarget::EventTarget;
use dom::globalscope::GlobalScope;
use hyper::header::{Accept, qitem};
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use mime::{Mime, TopLevel, SubLevel};
use net_traits::{CoreResourceMsg, FetchMetadata, FetchResponseListener, NetworkError};
use net_traits::request::{CacheMode, CorsSettings, CredentialsMode};
use net_traits::request::{RequestInit, RequestMode};
use network_listener::{NetworkListener, PreInvoke};
use script_thread::{Runnable, RunnableWrapper};
use std::cell::Cell;
use std::sync::{Arc, Mutex};
use task_source::TaskSource;
use task_source::networking::NetworkingTaskSource;
use url::Url;

#[derive(JSTraceable, PartialEq, Copy, Clone, Debug, HeapSizeOf)]
/// https://html.spec.whatwg.org/multipage/#dom-eventsource-readystate
enum ReadyState {
    Connecting = 0,
    Open = 1,
    Closed = 2
}

#[dom_struct]
pub struct EventSource {
    eventtarget: EventTarget,
    url: DOMRefCell<Option<Url>>,
    request: DOMRefCell<Option<RequestInit>>,
    ready_state: Cell<ReadyState>,
    with_credentials: bool,
    last_event_id: DOMRefCell<DOMString>
}

struct EventSourceContext {
    event_source: Trusted<EventSource>,
    networking_task_source: NetworkingTaskSource,
    wrapper: RunnableWrapper
}

impl EventSourceContext {
    fn announce_the_connection(&self) {
        let runnable = box AnnounceConnectionRunnable {
            event_source: self.event_source.clone()
        };
        let _ = self.networking_task_source.queue_with_wrapper(runnable, &self.wrapper);
    }

    fn fail_the_connection(&self) {
        let runnable = box FailConnectionRunnable {
            event_source: self.event_source.clone()
        };
        let _ = self.networking_task_source.queue_with_wrapper(runnable, &self.wrapper);
    }
}

impl FetchResponseListener for EventSourceContext {
    fn process_request_body(&mut self) {
        // TODO
    }

    fn process_request_eof(&mut self) {
        // TODO
    }

    fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>) {
        match metadata {
            Ok(fm) => {
                let meta = match fm {
                    FetchMetadata::Unfiltered(m) => m,
                    FetchMetadata::Filtered { unsafe_, .. } => unsafe_
                };
                match meta.content_type {
                    None => self.fail_the_connection(),
                    Some(ct) => match ct.into_inner().0 {
                        Mime(TopLevel::Text, SubLevel::EventStream, _) =>
                            self.announce_the_connection(),
                        _ => self.fail_the_connection()
                    }
                }
            }
            Err(_) => {
                // FIXME: Fail the connection for now, but it should really attempt to re-establish
                self.fail_the_connection();
            }
        }
    }

    fn process_response_chunk(&mut self, mut _chunk: Vec<u8>) {
        // TODO
    }

    fn process_response_eof(&mut self, _response: Result<(), NetworkError>) {
        // TODO
    }
}

impl PreInvoke for EventSourceContext {}

impl EventSource {
    fn new_inherited(with_credentials: bool) -> EventSource {
        EventSource {
            eventtarget: EventTarget::new_inherited(),
            url: DOMRefCell::new(None),
            request: DOMRefCell::new(None),
            ready_state: Cell::new(ReadyState::Connecting),
            with_credentials: with_credentials,
            last_event_id: DOMRefCell::new(DOMString::from(""))
        }
    }

    fn new(global: &GlobalScope, with_credentials: bool) -> Root<EventSource> {
        reflect_dom_object(box EventSource::new_inherited(with_credentials),
                           global,
                           Wrap)
    }

    pub fn Constructor(global: &GlobalScope,
                       url: DOMString,
                       event_source_init: &EventSourceInit) -> Fallible<Root<EventSource>> {
        // Step 1
        let ev = EventSource::new(global, event_source_init.withCredentials);
        // TODO: Step 2 relevant settings object
        // Step 3
        let base_url = global.api_base_url();
        let url_record = match base_url.join(&*url) {
            Ok(u) => u,
            //  Step 4
            Err(_) => return Err(Error::Syntax)
        };
        // Step 5
        *ev.url.borrow_mut() = Some(url_record.clone());
        // Steps 6-7
        let cors_attribute_state = if event_source_init.withCredentials {
            CorsSettings::UseCredentials
        } else {
            CorsSettings::Anonymous
        };
        // Step 8
        // TODO: Step 9 set request's client settings
        let mut request = RequestInit {
            url: url_record,
            origin: global.get_url(),
            pipeline_id: Some(global.pipeline_id()),
            // https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request
            use_url_credentials: true,
            mode: RequestMode::CorsMode,
            credentials_mode: if cors_attribute_state == CorsSettings::Anonymous {
                CredentialsMode::CredentialsSameOrigin
            } else {
                CredentialsMode::Include
            },
            ..RequestInit::default()
        };
        // Step 10
        request.headers.set(Accept(vec![qitem(mime!(Text / EventStream))]));
        // Step 11
        request.cache_mode = CacheMode::NoStore;
        // Step 12
        *ev.request.borrow_mut() = Some(request.clone());
        // Step 14
        let context = EventSourceContext {
            event_source: Trusted::new(&ev),
            networking_task_source: global.networking_task_source(),
            wrapper: global.get_runnable_wrapper()
        };
        let listener = NetworkListener {
            context: Arc::new(Mutex::new(context)),
            task_source: global.networking_task_source(),
            wrapper: Some(global.get_runnable_wrapper())
        };
        let (action_sender, action_receiver) = ipc::channel().unwrap();
        ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
            listener.notify_fetch(message.to().unwrap());
        });
        global.core_resource_thread().send(CoreResourceMsg::Fetch(request, action_sender)).unwrap();
        // Step 13
        Ok(ev)
    }
}

impl EventSourceMethods for EventSource {
    // https://html.spec.whatwg.org/multipage/#handler-eventsource-onopen
    event_handler!(open, GetOnopen, SetOnopen);

    // https://html.spec.whatwg.org/multipage/#handler-eventsource-onmessage
    event_handler!(message, GetOnmessage, SetOnmessage);

    // https://html.spec.whatwg.org/multipage/#handler-eventsource-onerror
    event_handler!(error, GetOnerror, SetOnerror);

    // https://html.spec.whatwg.org/multipage/#dom-eventsource-url
    fn Url(&self) -> DOMString {
        DOMString::from(self.url.borrow().clone().map_or("".to_owned(), Url::into_string))
    }

    // https://html.spec.whatwg.org/multipage/#dom-eventsource-withcredentials
    fn WithCredentials(&self) -> bool {
        self.with_credentials
    }

    // https://html.spec.whatwg.org/multipage/#dom-eventsource-readystate
    fn ReadyState(&self) -> u16 {
        self.ready_state.get() as u16
    }

    // https://html.spec.whatwg.org/multipage/#dom-eventsource-close
    fn Close(&self) {
        self.ready_state.set(ReadyState::Closed);
        // TODO: Terminate ongoing fetch
    }
}

pub struct AnnounceConnectionRunnable {
    event_source: Trusted<EventSource>,
}

impl Runnable for AnnounceConnectionRunnable {
    fn name(&self) -> &'static str { "EventSource AnnounceConnectionRunnable" }

    // https://html.spec.whatwg.org/multipage/#announce-the-connection
    fn handler(self: Box<AnnounceConnectionRunnable>) {
        let event_source = self.event_source.root();
        if event_source.ready_state.get() != ReadyState::Closed {
            event_source.ready_state.set(ReadyState::Open);
            event_source.upcast::<EventTarget>().fire_event(atom!("open"));
        }
    }
}

pub struct FailConnectionRunnable {
    event_source: Trusted<EventSource>,
}

impl Runnable for FailConnectionRunnable {
    fn name(&self) -> &'static str { "EventSource FailConnectionRunnable" }

    // https://html.spec.whatwg.org/multipage/#fail-the-connection
    fn handler(self: Box<FailConnectionRunnable>) {
        let event_source = self.event_source.root();
        if event_source.ready_state.get() != ReadyState::Closed {
            event_source.ready_state.set(ReadyState::Closed);
            event_source.upcast::<EventTarget>().fire_event(atom!("error"));
        }
    }
}
<|endoftext|>


<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/. */

use dom::bindings::codegen::Bindings::PermissionStatusBinding::{PermissionDescriptor, PermissionName, PermissionState};
use dom::bindings::codegen::Bindings::PermissionsBinding::{self, PermissionsMethods};
use dom::bindings::error::Error;
use dom::bindings::js::Root;
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
use dom::bluetooth::Bluetooth;
use dom::bluetoothpermissionresult::BluetoothPermissionResult;
use dom::globalscope::GlobalScope;
use dom::permissionstatus::PermissionStatus;
use dom::promise::Promise;
use js::conversions::ConversionResult;
use js::jsapi::{JSContext, JSObject};
use js::jsval::{ObjectValue, UndefinedValue};
use std::rc::Rc;
#[cfg(target_os = "linux")]
use tinyfiledialogs::{self, MessageBoxIcon, YesNo};

#[cfg(target_os = "linux")]
const DIALOG_TITLE: &'static str = "Permission request dialog";
#[cfg(target_os = "linux")]
const QUERY_DIALOG_MESSAGE: &'static str = "Can't guarantee, that the current context is secure.
\t\tStill grant permission for";
const ROOT_DESC_CONVERSION_ERROR: &'static str = "Can't convert to an IDL value of type PermissionDescriptor";

pub trait PermissionAlgorithm {
    type Descriptor;
    type Status;
    fn create_descriptor(cx: *mut JSContext,
                         permission_descriptor_obj: *mut JSObject)
                         -> Result<Self::Descriptor, Error>;
    fn permission_query(cx: *mut JSContext, promise: &Rc<Promise>,
                        descriptor: &Self::Descriptor, status: &Self::Status);
    fn permission_request(cx: *mut JSContext, promise: &Rc<Promise>,
                          descriptor: &Self::Descriptor, status: &Self::Status);
    fn permission_revoke(descriptor: &Self::Descriptor, status: &Self::Status);
}

// https://w3c.github.io/permissions/#permissions
#[dom_struct]
pub struct Permissions {
    reflector_: Reflector,
}

impl Permissions {
    pub fn new_inherited() -> Permissions {
        Permissions {
            reflector_: Reflector::new(),
        }
    }

    pub fn new(global: &GlobalScope) -> Root<Permissions> {
        reflect_dom_object(box Permissions::new_inherited(),
                           global,
                           PermissionsBinding::Wrap)
    }
}

impl PermissionsMethods for Permissions {
    #[allow(unrooted_must_root)]
    #[allow(unsafe_code)]
    // https://w3c.github.io/permissions/#dom-permissions-query
    unsafe fn Query(&self, cx: *mut JSContext, permissionDesc: *mut JSObject) -> Rc<Promise> {
        // Step 3.
        let p = Promise::new(&self.global());

        // Step 1.
        let root_desc = match Permissions::create_descriptor(cx, permissionDesc) {
            Ok(descriptor) => descriptor,
            Err(error) => {
                p.reject_error(cx, error);
                return p;
            },
        };

        // Step 5.
        let status = PermissionStatus::new(&self.global(), &root_desc);

        // Step 2.
        match root_desc.name {
            PermissionName::Bluetooth => {
                let bluetooth_desc = match Bluetooth::create_descriptor(cx, permissionDesc) {
                    Ok(descriptor) => descriptor,
                    Err(error) => {
                        p.reject_error(cx, error);
                        return p;
                    },
                };
                // Step 5.
                let result = BluetoothPermissionResult::new(&self.global(), &status);
                // Step 6.
                Bluetooth::permission_query(cx, &p, &bluetooth_desc, &result);
                // Step 7. in permission_query
            },
            _ => {
                // Step 6.
                Permissions::permission_query(cx, &p, &root_desc, &status);

                // Step 7.
                p.resolve_native(cx, &status);
            },
        };

        // Step 4.
        return p;
    }

    #[allow(unrooted_must_root)]
    #[allow(unsafe_code)]
    // https://w3c.github.io/permissions/#dom-permissions-request
    unsafe fn Request(&self, cx: *mut JSContext, permissionDesc: *mut JSObject) -> Rc<Promise> {
        // Step 3.
        let p = Promise::new(&self.global());

        // Step 1.
        let root_desc = match Permissions::create_descriptor(cx, permissionDesc) {
            Ok(descriptor) => descriptor,
            Err(error) => {
                p.reject_error(cx, error);
                return p;
            },
        };

        // Step 5.
        let status = PermissionStatus::new(&self.global(), &root_desc);

        // Step 2.
        match root_desc.name {
            PermissionName::Bluetooth => {
                let bluetooth_desc = match Bluetooth::create_descriptor(cx, permissionDesc) {
                    Ok(descriptor) => descriptor,
                    Err(error) => {
                        p.reject_error(cx, error);
                        return p;
                    },
                };
                // Step 5.
                let result = BluetoothPermissionResult::new(&self.global(), &status);
                // Step 6.
                Bluetooth::permission_request(cx, &p, &bluetooth_desc, &result);
                // Step 7 - 8. in permission_request
            },
            _ => {
                // Step 6.
                Permissions::permission_request(cx, &p, &root_desc, &status);

                // Step 7. The default algorithm always resolve

                // Step 8.
                p.resolve_native(cx, &status);
            },
        };
        // Step 4.
        return p;
    }

    #[allow(unrooted_must_root)]
    #[allow(unsafe_code)]
    // https://w3c.github.io/permissions/#dom-permissions-revoke
    unsafe fn Revoke(&self, cx: *mut JSContext, permissionDesc: *mut JSObject) -> Rc<Promise> {
        // Step 1.
        let root_desc = match Permissions::create_descriptor(cx, permissionDesc) {
            Ok(descriptor) => descriptor,
            Err(error) => {
                let p = Promise::new(&self.global());
                p.reject_error(cx, error);
                return p;
            },
        };

        let status = PermissionStatus::new(&self.global(), &root_desc);

        // Step 2.
        match root_desc.name {
            PermissionName::Bluetooth => {
                let bluetooth_desc = match Bluetooth::create_descriptor(cx, permissionDesc) {
                    Ok(descriptor) => descriptor,
                    Err(error) => {
                        let p = Promise::new(&self.global());
                        p.reject_error(cx, error);
                        return p;
                    },
                };
                let result = BluetoothPermissionResult::new(&self.global(), &status);
                // Step 3 - 4. in permission_revoke
                Bluetooth::permission_revoke(&bluetooth_desc, &result);
            },
            _ => {
                Permissions::permission_revoke(&root_desc, &status);
            },
        };

        // Step 5.
        return self.Query(cx, permissionDesc);
    }
}

impl PermissionAlgorithm for Permissions {
    type Descriptor = PermissionDescriptor;
    type Status = PermissionStatus;

    #[allow(unsafe_code)]
    fn create_descriptor(cx: *mut JSContext,
                         permission_descriptor_obj: *mut JSObject)
                         -> Result<PermissionDescriptor, Error> {
        rooted!(in(cx) let mut property = UndefinedValue());
        property.handle_mut().set(ObjectValue(permission_descriptor_obj));
        unsafe {
            match PermissionDescriptor::new(cx, property.handle()) {
                Ok(ConversionResult::Success(descriptor)) => Ok(descriptor),
                Ok(ConversionResult::Failure(error)) => Err(Error::Type(error.into_owned())),
                Err(_) => Err(Error::Type(String::from(ROOT_DESC_CONVERSION_ERROR))),
            }
        }
    }

    // https://w3c.github.io/permissions/#boolean-permission-query-algorithm
    fn permission_query(_cx: *mut JSContext,
                        _promise: &Rc<Promise>,
                        _descriptor: &PermissionDescriptor,
                        status: &PermissionStatus) {
        // Step 1.
        status.set_state(get_descriptor_permission_state(status.get_query(), None));
    }

    // https://w3c.github.io/permissions/#boolean-permission-request-algorithm
    fn permission_request(cx: *mut JSContext,
                          promise: &Rc<Promise>,
                          descriptor: &PermissionDescriptor,
                          status: &PermissionStatus) {
        // Step 1.
        Permissions::permission_query(cx, promise, descriptor, status);

        // TODO: Step 2 - 4: `environment settings object` is not implemented in Servo yet.
        // For this reason in the `get_descriptor_permission_state` function we can't decide
        // if we have a secure context or not, or store the previous invocation results.
        // Without these the remaining steps can't be implemented properly.
    }

    fn permission_revoke(_descriptor: &PermissionDescriptor, _status: &PermissionStatus) {}
}

// https://w3c.github.io/permissions/#permission-state
pub fn get_descriptor_permission_state(permission_name: PermissionName ,
                                       _env_settings_obj: Option<*mut JSObject>)
                                       -> PermissionState {
    // TODO: Step 1: If settings wasn’t passed, set it to the current settings object.
    // TODO: `environment settings object` is not implemented in Servo yet.

    // Step 2.
    // TODO: The `is the environment settings object a non-secure context` check is missing.
    // The current solution is a workaround with a message box to warn about this,
    // if the feature is not allowed in non-secure contexcts,
    // and let the user decide to grant the permission or not.
    if !allowed_in_nonsecure_contexts(&permission_name) {
        if cfg!(target_os = "linux") {
            match tinyfiledialogs::message_box_yes_no(DIALOG_TITLE,
                                                      &format!("{} {:?} ?", QUERY_DIALOG_MESSAGE, permission_name),
                                                      MessageBoxIcon::Question,
                                                      YesNo::No) {
                YesNo::Yes => return PermissionState::Granted,
                YesNo::No => return PermissionState::Denied,
            };
        } else {
            return PermissionState::Denied;
        }
    }

    // TODO: Step 3: Store the invocation results
    // TODO: `environment settings object` is not implemented in Servo yet.

    // Step 4.
    PermissionState::Granted
}

// https://w3c.github.io/permissions/#allowed-in-non-secure-contexts
fn allowed_in_nonsecure_contexts(permission_name: &PermissionName) -> bool {
    match *permission_name {
        // https://w3c.github.io/permissions/#dom-permissionname-geolocation
        PermissionName::Geolocation => true,
        // https://w3c.github.io/permissions/#dom-permissionname-notifications
        PermissionName::Notifications => true,
        // https://w3c.github.io/permissions/#dom-permissionname-push
        PermissionName::Push => false,
        // https://w3c.github.io/permissions/#dom-permissionname-midi
        PermissionName::Midi => true,
        // https://w3c.github.io/permissions/#dom-permissionname-camera
        PermissionName::Camera => false,
        // https://w3c.github.io/permissions/#dom-permissionname-microphone
        PermissionName::Microphone => false,
        // https://w3c.github.io/permissions/#dom-permissionname-speaker
        PermissionName::Speaker => false,
        // https://w3c.github.io/permissions/#dom-permissionname-device-info
        PermissionName::Device_info => false,
        // https://w3c.github.io/permissions/#dom-permissionname-background-sync
        PermissionName::Background_sync => false,
        // https://webbluetoothcg.github.io/web-bluetooth/#dom-permissionname-bluetooth
        PermissionName::Bluetooth => false,
        // https://storage.spec.whatwg.org/#dom-permissionname-persistent-storage
        PermissionName::Persistent_storage => false,
    }
}
<commit_msg>Fix popup build error<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/. */

use dom::bindings::codegen::Bindings::PermissionStatusBinding::{PermissionDescriptor, PermissionName, PermissionState};
use dom::bindings::codegen::Bindings::PermissionsBinding::{self, PermissionsMethods};
use dom::bindings::error::Error;
use dom::bindings::js::Root;
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
use dom::bluetooth::Bluetooth;
use dom::bluetoothpermissionresult::BluetoothPermissionResult;
use dom::globalscope::GlobalScope;
use dom::permissionstatus::PermissionStatus;
use dom::promise::Promise;
use js::conversions::ConversionResult;
use js::jsapi::{JSContext, JSObject};
use js::jsval::{ObjectValue, UndefinedValue};
use std::rc::Rc;
#[cfg(target_os = "linux")]
use tinyfiledialogs::{self, MessageBoxIcon, YesNo};

#[cfg(target_os = "linux")]
const DIALOG_TITLE: &'static str = "Permission request dialog";
#[cfg(target_os = "linux")]
const QUERY_DIALOG_MESSAGE: &'static str = "Can't guarantee, that the current context is secure.
\t\tStill grant permission for";
const ROOT_DESC_CONVERSION_ERROR: &'static str = "Can't convert to an IDL value of type PermissionDescriptor";

pub trait PermissionAlgorithm {
    type Descriptor;
    type Status;
    fn create_descriptor(cx: *mut JSContext,
                         permission_descriptor_obj: *mut JSObject)
                         -> Result<Self::Descriptor, Error>;
    fn permission_query(cx: *mut JSContext, promise: &Rc<Promise>,
                        descriptor: &Self::Descriptor, status: &Self::Status);
    fn permission_request(cx: *mut JSContext, promise: &Rc<Promise>,
                          descriptor: &Self::Descriptor, status: &Self::Status);
    fn permission_revoke(descriptor: &Self::Descriptor, status: &Self::Status);
}

// https://w3c.github.io/permissions/#permissions
#[dom_struct]
pub struct Permissions {
    reflector_: Reflector,
}

impl Permissions {
    pub fn new_inherited() -> Permissions {
        Permissions {
            reflector_: Reflector::new(),
        }
    }

    pub fn new(global: &GlobalScope) -> Root<Permissions> {
        reflect_dom_object(box Permissions::new_inherited(),
                           global,
                           PermissionsBinding::Wrap)
    }
}

impl PermissionsMethods for Permissions {
    #[allow(unrooted_must_root)]
    #[allow(unsafe_code)]
    // https://w3c.github.io/permissions/#dom-permissions-query
    unsafe fn Query(&self, cx: *mut JSContext, permissionDesc: *mut JSObject) -> Rc<Promise> {
        // Step 3.
        let p = Promise::new(&self.global());

        // Step 1.
        let root_desc = match Permissions::create_descriptor(cx, permissionDesc) {
            Ok(descriptor) => descriptor,
            Err(error) => {
                p.reject_error(cx, error);
                return p;
            },
        };

        // Step 5.
        let status = PermissionStatus::new(&self.global(), &root_desc);

        // Step 2.
        match root_desc.name {
            PermissionName::Bluetooth => {
                let bluetooth_desc = match Bluetooth::create_descriptor(cx, permissionDesc) {
                    Ok(descriptor) => descriptor,
                    Err(error) => {
                        p.reject_error(cx, error);
                        return p;
                    },
                };
                // Step 5.
                let result = BluetoothPermissionResult::new(&self.global(), &status);
                // Step 6.
                Bluetooth::permission_query(cx, &p, &bluetooth_desc, &result);
                // Step 7. in permission_query
            },
            _ => {
                // Step 6.
                Permissions::permission_query(cx, &p, &root_desc, &status);

                // Step 7.
                p.resolve_native(cx, &status);
            },
        };

        // Step 4.
        return p;
    }

    #[allow(unrooted_must_root)]
    #[allow(unsafe_code)]
    // https://w3c.github.io/permissions/#dom-permissions-request
    unsafe fn Request(&self, cx: *mut JSContext, permissionDesc: *mut JSObject) -> Rc<Promise> {
        // Step 3.
        let p = Promise::new(&self.global());

        // Step 1.
        let root_desc = match Permissions::create_descriptor(cx, permissionDesc) {
            Ok(descriptor) => descriptor,
            Err(error) => {
                p.reject_error(cx, error);
                return p;
            },
        };

        // Step 5.
        let status = PermissionStatus::new(&self.global(), &root_desc);

        // Step 2.
        match root_desc.name {
            PermissionName::Bluetooth => {
                let bluetooth_desc = match Bluetooth::create_descriptor(cx, permissionDesc) {
                    Ok(descriptor) => descriptor,
                    Err(error) => {
                        p.reject_error(cx, error);
                        return p;
                    },
                };
                // Step 5.
                let result = BluetoothPermissionResult::new(&self.global(), &status);
                // Step 6.
                Bluetooth::permission_request(cx, &p, &bluetooth_desc, &result);
                // Step 7 - 8. in permission_request
            },
            _ => {
                // Step 6.
                Permissions::permission_request(cx, &p, &root_desc, &status);

                // Step 7. The default algorithm always resolve

                // Step 8.
                p.resolve_native(cx, &status);
            },
        };
        // Step 4.
        return p;
    }

    #[allow(unrooted_must_root)]
    #[allow(unsafe_code)]
    // https://w3c.github.io/permissions/#dom-permissions-revoke
    unsafe fn Revoke(&self, cx: *mut JSContext, permissionDesc: *mut JSObject) -> Rc<Promise> {
        // Step 1.
        let root_desc = match Permissions::create_descriptor(cx, permissionDesc) {
            Ok(descriptor) => descriptor,
            Err(error) => {
                let p = Promise::new(&self.global());
                p.reject_error(cx, error);
                return p;
            },
        };

        let status = PermissionStatus::new(&self.global(), &root_desc);

        // Step 2.
        match root_desc.name {
            PermissionName::Bluetooth => {
                let bluetooth_desc = match Bluetooth::create_descriptor(cx, permissionDesc) {
                    Ok(descriptor) => descriptor,
                    Err(error) => {
                        let p = Promise::new(&self.global());
                        p.reject_error(cx, error);
                        return p;
                    },
                };
                let result = BluetoothPermissionResult::new(&self.global(), &status);
                // Step 3 - 4. in permission_revoke
                Bluetooth::permission_revoke(&bluetooth_desc, &result);
            },
            _ => {
                Permissions::permission_revoke(&root_desc, &status);
            },
        };

        // Step 5.
        return self.Query(cx, permissionDesc);
    }
}

impl PermissionAlgorithm for Permissions {
    type Descriptor = PermissionDescriptor;
    type Status = PermissionStatus;

    #[allow(unsafe_code)]
    fn create_descriptor(cx: *mut JSContext,
                         permission_descriptor_obj: *mut JSObject)
                         -> Result<PermissionDescriptor, Error> {
        rooted!(in(cx) let mut property = UndefinedValue());
        property.handle_mut().set(ObjectValue(permission_descriptor_obj));
        unsafe {
            match PermissionDescriptor::new(cx, property.handle()) {
                Ok(ConversionResult::Success(descriptor)) => Ok(descriptor),
                Ok(ConversionResult::Failure(error)) => Err(Error::Type(error.into_owned())),
                Err(_) => Err(Error::Type(String::from(ROOT_DESC_CONVERSION_ERROR))),
            }
        }
    }

    // https://w3c.github.io/permissions/#boolean-permission-query-algorithm
    fn permission_query(_cx: *mut JSContext,
                        _promise: &Rc<Promise>,
                        _descriptor: &PermissionDescriptor,
                        status: &PermissionStatus) {
        // Step 1.
        status.set_state(get_descriptor_permission_state(status.get_query(), None));
    }

    // https://w3c.github.io/permissions/#boolean-permission-request-algorithm
    fn permission_request(cx: *mut JSContext,
                          promise: &Rc<Promise>,
                          descriptor: &PermissionDescriptor,
                          status: &PermissionStatus) {
        // Step 1.
        Permissions::permission_query(cx, promise, descriptor, status);

        // TODO: Step 2 - 4: `environment settings object` is not implemented in Servo yet.
        // For this reason in the `get_descriptor_permission_state` function we can't decide
        // if we have a secure context or not, or store the previous invocation results.
        // Without these the remaining steps can't be implemented properly.
    }

    fn permission_revoke(_descriptor: &PermissionDescriptor, _status: &PermissionStatus) {}
}

// https://w3c.github.io/permissions/#permission-state
pub fn get_descriptor_permission_state(permission_name: PermissionName ,
                                       _env_settings_obj: Option<*mut JSObject>)
                                       -> PermissionState {
    // TODO: Step 1: If settings wasn’t passed, set it to the current settings object.
    // TODO: `environment settings object` is not implemented in Servo yet.

    // Step 2.
    // TODO: The `is the environment settings object a non-secure context` check is missing.
    // The current solution is a workaround with a message box to warn about this,
    // if the feature is not allowed in non-secure contexcts,
    // and let the user decide to grant the permission or not.
    if !allowed_in_nonsecure_contexts(&permission_name) {
        return prompt_user(permission_name);
    }

    // TODO: Step 3: Store the invocation results
    // TODO: `environment settings object` is not implemented in Servo yet.

    // Step 4.
    PermissionState::Granted
}

#[cfg(target_os = "linux")]
fn prompt_user(permission_name: PermissionName) -> PermissionState {
    match tinyfiledialogs::message_box_yes_no(DIALOG_TITLE,
                                              &format!("{} {:?} ?", QUERY_DIALOG_MESSAGE, permission_name),
                                              MessageBoxIcon::Question,
                                              YesNo::No) {
        YesNo::Yes => return PermissionState::Granted,
        YesNo::No => return PermissionState::Denied,
    };
}

#[cfg(not(target_os = "linux"))]
fn prompt_user(_permission_name: PermissionName) -> PermissionState {
    // TODO popup only supported on linux
    PermissionState::Denied
}

// https://w3c.github.io/permissions/#allowed-in-non-secure-contexts
fn allowed_in_nonsecure_contexts(permission_name: &PermissionName) -> bool {
    match *permission_name {
        // https://w3c.github.io/permissions/#dom-permissionname-geolocation
        PermissionName::Geolocation => true,
        // https://w3c.github.io/permissions/#dom-permissionname-notifications
        PermissionName::Notifications => true,
        // https://w3c.github.io/permissions/#dom-permissionname-push
        PermissionName::Push => false,
        // https://w3c.github.io/permissions/#dom-permissionname-midi
        PermissionName::Midi => true,
        // https://w3c.github.io/permissions/#dom-permissionname-camera
        PermissionName::Camera => false,
        // https://w3c.github.io/permissions/#dom-permissionname-microphone
        PermissionName::Microphone => false,
        // https://w3c.github.io/permissions/#dom-permissionname-speaker
        PermissionName::Speaker => false,
        // https://w3c.github.io/permissions/#dom-permissionname-device-info
        PermissionName::Device_info => false,
        // https://w3c.github.io/permissions/#dom-permissionname-background-sync
        PermissionName::Background_sync => false,
        // https://webbluetoothcg.github.io/web-bluetooth/#dom-permissionname-bluetooth
        PermissionName::Bluetooth => false,
        // https://storage.spec.whatwg.org/#dom-permissionname-persistent-storage
        PermissionName::Persistent_storage => false,
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::path::PathBuf;

fn main() {
    println!("cargo:rerun-if-changed=CRoaring");
    println!("cargo:rerun-if-env-changed=ROARING_ARCH");

    let mut build = cc::Build::new();
    build.file("CRoaring/roaring.c");

    if let Ok(target_arch) = env::var("ROARING_ARCH") {
        build.flag_if_supported(&format!("-march={}", target_arch));
    }

    build.flag_if_supported("-Wno-unused-function");
    build.compile("libroaring.a");

    let bindings = bindgen::Builder::default()
        .header("CRoaring/roaring.h")
        .generate_inline_functions(true)
        .allowlist_function("roaring.*")
        .allowlist_type("roaring.*")
        .allowlist_var("roaring.*")
        .allowlist_var("ROARING.*")
        .generate()
        .expect("Unable to generate bindings");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("croaring-sys.rs"))
        .expect("Couldn't write bindings!");
}
<commit_msg>Pass only the base library name to cc::Build::compile<commit_after>use std::env;
use std::path::PathBuf;

fn main() {
    println!("cargo:rerun-if-changed=CRoaring");
    println!("cargo:rerun-if-env-changed=ROARING_ARCH");

    let mut build = cc::Build::new();
    build.file("CRoaring/roaring.c");

    if let Ok(target_arch) = env::var("ROARING_ARCH") {
        build.flag_if_supported(&format!("-march={}", target_arch));
    }

    build.flag_if_supported("-Wno-unused-function");
    build.compile("roaring");

    let bindings = bindgen::Builder::default()
        .header("CRoaring/roaring.h")
        .generate_inline_functions(true)
        .allowlist_function("roaring.*")
        .allowlist_type("roaring.*")
        .allowlist_var("roaring.*")
        .allowlist_var("ROARING.*")
        .generate()
        .expect("Unable to generate bindings");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("croaring-sys.rs"))
        .expect("Couldn't write bindings!");
}
<|endoftext|>


<commit_before>#![feature(test, plugin)]
#![plugin(clippy)]
#![deny(clippy, clippy_pedantic)]

extern crate compiletest_rs as compiletest;
extern crate test;

use std::env::{var, set_var, temp_dir};
use std::path::PathBuf;
use test::TestPaths;

#[test]
fn dogfood() {
    let mut config = compiletest::default_config();

    let cfg_mode = "run-fail".parse().expect("Invalid mode");
    let mut s = String::new();
    s.push_str(" -L target/debug/");
    s.push_str(" -L target/debug/deps");
    s.push_str(" -Zextra-plugins=clippy -Ltarget_recur/debug -Dclippy_pedantic -Dclippy -Dclippy_lints_internal");
    config.target_rustcflags = Some(s);
    if let Ok(name) = var("TESTNAME") {
        config.filter = Some(name.to_owned())
    }

    if cfg!(windows) {
        // work around https://github.com/laumann/compiletest-rs/issues/35 on msvc windows
        config.build_base = temp_dir();
    }

    config.mode = cfg_mode;
    config.verbose = true;

    let files = ["src/main.rs", "src/lib.rs", "clippy_lints/src/lib.rs"];

    for file in &files {
        let paths = TestPaths {
            base: PathBuf::new(),
            file: PathBuf::from(file),
            relative_dir: PathBuf::new(),
        };

        set_var("CLIPPY_DOGFOOD", "tastes like chicken");

        compiletest::runtest::run(config.clone(), &paths);
    }
}
<commit_msg>don't run clippy on itself twice in travis<commit_after>#![feature(test, plugin)]
#![plugin(clippy)]
#![deny(clippy, clippy_pedantic)]

extern crate compiletest_rs as compiletest;
extern crate test;

use std::env::{var, set_var};
use std::path::PathBuf;
use test::TestPaths;

#[test]
fn dogfood() {
    // don't run dogfood on travis, cargo-clippy already runs clippy on itself
    if let Ok(travis) = var("TRAVIS") {
        if travis == "true" {
            return;
        }
    }

    let mut config = compiletest::default_config();

    let cfg_mode = "run-fail".parse().expect("Invalid mode");
    let mut s = String::new();
    s.push_str(" -L target/debug/");
    s.push_str(" -L target/debug/deps");
    s.push_str(" -Zextra-plugins=clippy -Ltarget_recur/debug -Dclippy_pedantic -Dclippy -Dclippy_lints_internal");
    config.target_rustcflags = Some(s);
    if let Ok(name) = var("TESTNAME") {
        config.filter = Some(name.to_owned())
    }

    config.mode = cfg_mode;
    config.verbose = true;

    let files = ["src/main.rs", "src/lib.rs", "clippy_lints/src/lib.rs"];

    for file in &files {
        let paths = TestPaths {
            base: PathBuf::new(),
            file: PathBuf::from(file),
            relative_dir: PathBuf::new(),
        };

        set_var("CLIPPY_DOGFOOD", "tastes like chicken");

        compiletest::runtest::run(config.clone(), &paths);
    }
}
<|endoftext|>


<commit_before>/* Copyright 2016 Jordan Miner
 *
 * Licensed under the MIT license <LICENSE or
 * http://opensource.org/licenses/MIT>. This file may not be copied,
 * modified, or distributed except according to those terms.
 */

#[macro_use]
extern crate clear_coat;

use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
use std::cell::RefCell;
use std::rc::Rc;
use clear_coat::*;
use clear_coat::common_attrs_cbs::*;

// Tests that the get_focus callback works (which is most likely a test that the `simple_callback` function works).

static COUNTER: AtomicIsize = ATOMIC_ISIZE_INIT;

#[test]
fn test_get_focus_callback() {
    let button = Button::new();
    button.get_focus_event().add(move || { COUNTER.store(2, Ordering::Release); exit_loop(); });
    let dialog = Dialog::with_child(&vbox!(&button));
    //dialog.show_event().add(|_| CallbackAction::Close);

    dialog.show_xy(ScreenPosition::Center, ScreenPosition::Center).expect("could not show dialog");
    main_loop();
    assert_eq!(COUNTER.load(Ordering::Acquire), 2);
}
<commit_msg>Remove a couple of unused imports<commit_after>/* Copyright 2016 Jordan Miner
 *
 * Licensed under the MIT license <LICENSE or
 * http://opensource.org/licenses/MIT>. This file may not be copied,
 * modified, or distributed except according to those terms.
 */

#[macro_use]
extern crate clear_coat;

use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
use clear_coat::*;
use clear_coat::common_attrs_cbs::*;

// Tests that the get_focus callback works (which is most likely a test that the `simple_callback` function works).

static COUNTER: AtomicIsize = ATOMIC_ISIZE_INIT;

#[test]
fn test_get_focus_callback() {
    let button = Button::new();
    button.get_focus_event().add(move || { COUNTER.store(2, Ordering::Release); exit_loop(); });
    let dialog = Dialog::with_child(&vbox!(&button));
    //dialog.show_event().add(|_| CallbackAction::Close);

    dialog.show_xy(ScreenPosition::Center, ScreenPosition::Center).expect("could not show dialog");
    main_loop();
    assert_eq!(COUNTER.load(Ordering::Acquire), 2);
}
<|endoftext|>


<commit_before>/// This test suite prevents bitrot on examples/docs lichen source files
extern crate lichen;

use lichen::parse::Parser;
use lichen::eval::Eval;
use lichen::var::Var;

#[allow(dead_code)]
struct Data;

impl Eval for Data {
    #[allow(unused_variables)]
    fn get (&self, path: Option<Vec<&str>>, lookup: &str) -> Option<Var> {
        None
    }

    #[allow(unused_variables)]
    fn set (&mut self, path: Option<Vec<&str>>, lookup: &str, var: Var) {
    }

    #[allow(unused_variables)]
    fn call (&mut self, var: Var, fun: &str, vars: &Vec<Var>) -> Option<Var> {
        match fun {
            "inc" => {
                if let Ok(v) = Var::get_num(&var, self) {
                    let mut r = v;
                    for n in vars.iter() {
                        if let Ok(v) = Var::get_num(&n, self) {
                            r += v;
                        }
                    }

                    return Some(Var::Num(r))
                }
            },
            _ => { }
        }

        None
    }
}

#[test]
fn bitrot() {
    let mut src = vec![("basic", String::from_utf8_lossy(include_bytes!("../examples/basic.ls"))),
                       ("contrived", String::from_utf8_lossy(include_bytes!("../examples/contrived.ls"))),
                       ("syntax", String::from_utf8_lossy(include_bytes!("../docs/syntax.ls")))];

    for (file, mut src) in src.drain(..) {
        match Parser::parse_blocks(src.to_mut()) {
            Ok(p) => { p.into_env(); },
            Err(e) => { panic!("ERROR: Unable to parse source, {:} -- {:}", file, e) }
        }
    }
}
<commit_msg>add note<commit_after>/// This test suite prevents bitrot on examples/docs lichen source files
extern crate lichen;

use lichen::parse::Parser;
use lichen::eval::Eval;
use lichen::var::Var;

#[allow(dead_code)]
struct Data;

// we define this for the docs/syntax.ls to be tested against
impl Eval for Data {
    #[allow(unused_variables)]
    fn get (&self, path: Option<Vec<&str>>, lookup: &str) -> Option<Var> {
        None
    }

    #[allow(unused_variables)]
    fn set (&mut self, path: Option<Vec<&str>>, lookup: &str, var: Var) {
    }

    #[allow(unused_variables)]
    fn call (&mut self, var: Var, fun: &str, vars: &Vec<Var>) -> Option<Var> {
        match fun {
            "inc" => {
                if let Ok(v) = Var::get_num(&var, self) {
                    let mut r = v;
                    for n in vars.iter() {
                        if let Ok(v) = Var::get_num(&n, self) {
                            r += v;
                        }
                    }

                    return Some(Var::Num(r))
                }
            },
            _ => { }
        }

        None
    }
}

#[test]
fn bitrot() {
    let mut src = vec![("basic", String::from_utf8_lossy(include_bytes!("../examples/basic.ls"))),
                       ("contrived", String::from_utf8_lossy(include_bytes!("../examples/contrived.ls"))),
                       ("syntax", String::from_utf8_lossy(include_bytes!("../docs/syntax.ls")))];

    for (file, mut src) in src.drain(..) {
        match Parser::parse_blocks(src.to_mut()) {
            Ok(p) => { p.into_env(); },
            Err(e) => { panic!("ERROR: Unable to parse source, {:} -- {:}", file, e) }
        }
    }
}
<|endoftext|>


<commit_before>use lib::*;

use de::{
    Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor,
};

/// An efficient way of discarding data from a deserializer.
///
/// Think of this like `serde_json::Value` in that it can be deserialized from
/// any type, except that it does not store any information about the data that
/// gets deserialized.
///
/// ```edition2018
/// use std::fmt;
/// use std::marker::PhantomData;
///
/// use serde::de::{
///     self, Deserialize, DeserializeSeed, Deserializer, IgnoredAny, SeqAccess, Visitor,
/// };
///
/// /// A seed that can be used to deserialize only the `n`th element of a sequence
/// /// while efficiently discarding elements of any type before or after index `n`.
/// ///
/// /// For example to deserialize only the element at index 3:
/// ///
/// /// ```
/// /// NthElement::new(3).deserialize(deserializer)
/// /// ```
/// pub struct NthElement<T> {
///     n: usize,
///     marker: PhantomData<T>,
/// }
///
/// impl<T> NthElement<T> {
///     pub fn new(n: usize) -> Self {
///         NthElement {
///             n: n,
///             marker: PhantomData,
///         }
///     }
/// }
///
/// impl<'de, T> Visitor<'de> for NthElement<T>
/// where
///     T: Deserialize<'de>,
/// {
///     type Value = T;
///
///     fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
///         write!(
///             formatter,
///             "a sequence in which we care about element {}",
///             self.n
///         )
///     }
///
///     fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
///     where
///         A: SeqAccess<'de>,
///     {
///         // Skip over the first `n` elements.
///         for i in 0..self.n {
///             // It is an error if the sequence ends before we get to element `n`.
///             if seq.next_element::<IgnoredAny>()?.is_none() {
///                 return Err(de::Error::invalid_length(i, &self));
///             }
///         }
///
///         // Deserialize the one we care about.
///         let nth = match seq.next_element()? {
///             Some(nth) => nth,
///             None => {
///                 return Err(de::Error::invalid_length(self.n, &self));
///             }
///         };
///
///         // Skip over any remaining elements in the sequence after `n`.
///         while let Some(IgnoredAny) = seq.next_element()? {
///             // ignore
///         }
///
///         Ok(nth)
///     }
/// }
///
/// impl<'de, T> DeserializeSeed<'de> for NthElement<T>
/// where
///     T: Deserialize<'de>,
/// {
///     type Value = T;
///
///     fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
///     where
///         D: Deserializer<'de>,
///     {
///         deserializer.deserialize_seq(self)
///     }
/// }
///
/// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error>
/// # where
/// #     D: Deserializer<'de>,
/// # {
/// // Deserialize only the sequence element at index 3 from this deserializer.
/// // The element at index 3 is required to be a string. Elements before and
/// // after index 3 are allowed to be of any type.
/// let s: String = NthElement::new(3).deserialize(deserializer)?;
/// #     Ok(())
/// # }
/// ```
#[derive(Copy, Clone, Debug, Default)]
pub struct IgnoredAny;

impl<'de> Visitor<'de> for IgnoredAny {
    type Value = IgnoredAny;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("anything at all")
    }

    #[inline]
    fn visit_bool<E>(self, x: bool) -> Result<Self::Value, E> {
        let _ = x;
        Ok(IgnoredAny)
    }

    #[inline]
    fn visit_i64<E>(self, x: i64) -> Result<Self::Value, E> {
        let _ = x;
        Ok(IgnoredAny)
    }

    #[inline]
    fn visit_u64<E>(self, x: u64) -> Result<Self::Value, E> {
        let _ = x;
        Ok(IgnoredAny)
    }

    #[inline]
    fn visit_f64<E>(self, x: f64) -> Result<Self::Value, E> {
        let _ = x;
        Ok(IgnoredAny)
    }

    #[inline]
    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        let _ = s;
        Ok(IgnoredAny)
    }

    #[inline]
    fn visit_none<E>(self) -> Result<Self::Value, E> {
        Ok(IgnoredAny)
    }

    #[inline]
    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        IgnoredAny::deserialize(deserializer)
    }

    #[inline]
    fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        IgnoredAny::deserialize(deserializer)
    }

    #[inline]
    fn visit_unit<E>(self) -> Result<Self::Value, E> {
        Ok(IgnoredAny)
    }

    #[inline]
    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
    where
        A: SeqAccess<'de>,
    {
        while let Some(IgnoredAny) = try!(seq.next_element()) {
            // Gobble
        }
        Ok(IgnoredAny)
    }

    #[inline]
    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
    where
        A: MapAccess<'de>,
    {
        while let Some((IgnoredAny, IgnoredAny)) = try!(map.next_entry()) {
            // Gobble
        }
        Ok(IgnoredAny)
    }

    #[inline]
    fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
    where
        E: Error,
    {
        let _ = bytes;
        Ok(IgnoredAny)
    }

    fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
    where
        A: EnumAccess<'de>,
    {
        data.variant::<IgnoredAny>()?.1.newtype_variant()
    }
}

impl<'de> Deserialize<'de> for IgnoredAny {
    #[inline]
    fn deserialize<D>(deserializer: D) -> Result<IgnoredAny, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_ignored_any(IgnoredAny)
    }
}
<commit_msg>Add 128-bit integer support to de::IgnoredAny<commit_after>use lib::*;

use de::{
    Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor,
};

/// An efficient way of discarding data from a deserializer.
///
/// Think of this like `serde_json::Value` in that it can be deserialized from
/// any type, except that it does not store any information about the data that
/// gets deserialized.
///
/// ```edition2018
/// use std::fmt;
/// use std::marker::PhantomData;
///
/// use serde::de::{
///     self, Deserialize, DeserializeSeed, Deserializer, IgnoredAny, SeqAccess, Visitor,
/// };
///
/// /// A seed that can be used to deserialize only the `n`th element of a sequence
/// /// while efficiently discarding elements of any type before or after index `n`.
/// ///
/// /// For example to deserialize only the element at index 3:
/// ///
/// /// ```
/// /// NthElement::new(3).deserialize(deserializer)
/// /// ```
/// pub struct NthElement<T> {
///     n: usize,
///     marker: PhantomData<T>,
/// }
///
/// impl<T> NthElement<T> {
///     pub fn new(n: usize) -> Self {
///         NthElement {
///             n: n,
///             marker: PhantomData,
///         }
///     }
/// }
///
/// impl<'de, T> Visitor<'de> for NthElement<T>
/// where
///     T: Deserialize<'de>,
/// {
///     type Value = T;
///
///     fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
///         write!(
///             formatter,
///             "a sequence in which we care about element {}",
///             self.n
///         )
///     }
///
///     fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
///     where
///         A: SeqAccess<'de>,
///     {
///         // Skip over the first `n` elements.
///         for i in 0..self.n {
///             // It is an error if the sequence ends before we get to element `n`.
///             if seq.next_element::<IgnoredAny>()?.is_none() {
///                 return Err(de::Error::invalid_length(i, &self));
///             }
///         }
///
///         // Deserialize the one we care about.
///         let nth = match seq.next_element()? {
///             Some(nth) => nth,
///             None => {
///                 return Err(de::Error::invalid_length(self.n, &self));
///             }
///         };
///
///         // Skip over any remaining elements in the sequence after `n`.
///         while let Some(IgnoredAny) = seq.next_element()? {
///             // ignore
///         }
///
///         Ok(nth)
///     }
/// }
///
/// impl<'de, T> DeserializeSeed<'de> for NthElement<T>
/// where
///     T: Deserialize<'de>,
/// {
///     type Value = T;
///
///     fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
///     where
///         D: Deserializer<'de>,
///     {
///         deserializer.deserialize_seq(self)
///     }
/// }
///
/// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error>
/// # where
/// #     D: Deserializer<'de>,
/// # {
/// // Deserialize only the sequence element at index 3 from this deserializer.
/// // The element at index 3 is required to be a string. Elements before and
/// // after index 3 are allowed to be of any type.
/// let s: String = NthElement::new(3).deserialize(deserializer)?;
/// #     Ok(())
/// # }
/// ```
#[derive(Copy, Clone, Debug, Default)]
pub struct IgnoredAny;

impl<'de> Visitor<'de> for IgnoredAny {
    type Value = IgnoredAny;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("anything at all")
    }

    #[inline]
    fn visit_bool<E>(self, x: bool) -> Result<Self::Value, E> {
        let _ = x;
        Ok(IgnoredAny)
    }

    #[inline]
    fn visit_i64<E>(self, x: i64) -> Result<Self::Value, E> {
        let _ = x;
        Ok(IgnoredAny)
    }

    serde_if_integer128! {
        #[inline]
        fn visit_i128<E>(self, x: i128) -> Result<Self::Value, E> {
            let _ = x;
            Ok(IgnoredAny)
        }
    }

    #[inline]
    fn visit_u64<E>(self, x: u64) -> Result<Self::Value, E> {
        let _ = x;
        Ok(IgnoredAny)
    }

    serde_if_integer128! {
        #[inline]
        fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
            let _ = x;
            Ok(IgnoredAny)
        }
    }

    #[inline]
    fn visit_f64<E>(self, x: f64) -> Result<Self::Value, E> {
        let _ = x;
        Ok(IgnoredAny)
    }

    #[inline]
    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        let _ = s;
        Ok(IgnoredAny)
    }

    #[inline]
    fn visit_none<E>(self) -> Result<Self::Value, E> {
        Ok(IgnoredAny)
    }

    #[inline]
    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        IgnoredAny::deserialize(deserializer)
    }

    #[inline]
    fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        IgnoredAny::deserialize(deserializer)
    }

    #[inline]
    fn visit_unit<E>(self) -> Result<Self::Value, E> {
        Ok(IgnoredAny)
    }

    #[inline]
    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
    where
        A: SeqAccess<'de>,
    {
        while let Some(IgnoredAny) = try!(seq.next_element()) {
            // Gobble
        }
        Ok(IgnoredAny)
    }

    #[inline]
    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
    where
        A: MapAccess<'de>,
    {
        while let Some((IgnoredAny, IgnoredAny)) = try!(map.next_entry()) {
            // Gobble
        }
        Ok(IgnoredAny)
    }

    #[inline]
    fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
    where
        E: Error,
    {
        let _ = bytes;
        Ok(IgnoredAny)
    }

    fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
    where
        A: EnumAccess<'de>,
    {
        data.variant::<IgnoredAny>()?.1.newtype_variant()
    }
}

impl<'de> Deserialize<'de> for IgnoredAny {
    #[inline]
    fn deserialize<D>(deserializer: D) -> Result<IgnoredAny, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_ignored_any(IgnoredAny)
    }
}
<|endoftext|>


<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/. */

#![feature(append)]
#![feature(arc_unique)]
#![feature(as_unsafe_cell)]
#![feature(borrow_state)]
#![feature(box_raw)]
#![feature(box_syntax)]
#![feature(core)]
#![feature(core_intrinsics)]
#![feature(custom_attribute)]
#![feature(custom_derive)]
#![feature(drain)]
#![feature(hashmap_hasher)]
#![feature(mpsc_select)]
#![feature(nonzero)]
#![feature(owned_ascii_ext)]
#![feature(plugin)]
#![feature(rc_unique)]
#![feature(slice_chars)]
#![feature(str_utf16)]
#![feature(vec_push_all)]

#![deny(unsafe_code)]
#![allow(non_snake_case)]

#![doc="The script crate contains all matters DOM."]

#![plugin(string_cache_plugin)]
#![plugin(plugins)]

#[macro_use]
extern crate log;

#[macro_use] extern crate bitflags;
extern crate core;
extern crate devtools_traits;
extern crate cssparser;
extern crate euclid;
extern crate html5ever;
extern crate encoding;
extern crate fnv;
extern crate hyper;
extern crate js;
extern crate libc;
extern crate msg;
extern crate net_traits;
extern crate num;
extern crate png;
extern crate rustc_serialize;
extern crate time;
extern crate canvas;
extern crate canvas_traits;
extern crate profile_traits;
extern crate script_traits;
extern crate selectors;
extern crate smallvec;
extern crate util;
extern crate websocket;
#[macro_use]
extern crate style;
extern crate unicase;
extern crate url;
extern crate uuid;
extern crate string_cache;
extern crate offscreen_gl_context;
extern crate tendril;

pub mod cors;
pub mod document_loader;

#[macro_use]
pub mod dom;

pub mod parse;

pub mod layout_interface;
mod network_listener;
pub mod page;
pub mod script_task;
mod timers;
pub mod textinput;
pub mod clipboard_provider;
mod devtools;
mod horribly_inefficient_timers;
mod webdriver_handlers;

#[allow(unsafe_code)]
pub fn init() {
    unsafe {
        js::jsapi::JS_Init();
    }
}
<commit_msg>Auto merge of #6533 - Ms2ger:init, r=jdm<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/. */

#![feature(append)]
#![feature(arc_unique)]
#![feature(as_unsafe_cell)]
#![feature(borrow_state)]
#![feature(box_raw)]
#![feature(box_syntax)]
#![feature(core)]
#![feature(core_intrinsics)]
#![feature(custom_attribute)]
#![feature(custom_derive)]
#![feature(drain)]
#![feature(hashmap_hasher)]
#![feature(mpsc_select)]
#![feature(nonzero)]
#![feature(owned_ascii_ext)]
#![feature(plugin)]
#![feature(rc_unique)]
#![feature(slice_chars)]
#![feature(str_utf16)]
#![feature(vec_push_all)]

#![deny(unsafe_code)]
#![allow(non_snake_case)]

#![doc="The script crate contains all matters DOM."]

#![plugin(string_cache_plugin)]
#![plugin(plugins)]

#[macro_use]
extern crate log;

#[macro_use] extern crate bitflags;
extern crate core;
extern crate devtools_traits;
extern crate cssparser;
extern crate euclid;
extern crate html5ever;
extern crate encoding;
extern crate fnv;
extern crate hyper;
extern crate js;
extern crate libc;
extern crate msg;
extern crate net_traits;
extern crate num;
extern crate png;
extern crate rustc_serialize;
extern crate time;
extern crate canvas;
extern crate canvas_traits;
extern crate profile_traits;
extern crate script_traits;
extern crate selectors;
extern crate smallvec;
extern crate util;
extern crate websocket;
#[macro_use]
extern crate style;
extern crate unicase;
extern crate url;
extern crate uuid;
extern crate string_cache;
extern crate offscreen_gl_context;
extern crate tendril;

pub mod cors;
pub mod document_loader;

#[macro_use]
pub mod dom;

pub mod parse;

pub mod layout_interface;
mod network_listener;
pub mod page;
pub mod script_task;
mod timers;
pub mod textinput;
pub mod clipboard_provider;
mod devtools;
mod horribly_inefficient_timers;
mod webdriver_handlers;

#[allow(unsafe_code)]
pub fn init() {
    unsafe {
        assert_eq!(js::jsapi::JS_Init(), 1);
    }
}
<|endoftext|>


<commit_before>/*! ```compile_fail,E0501,E0382,E0597

extern crate futures;
extern crate rayon_core;
extern crate rayon_futures;

use futures::future::lazy;
use rayon_futures::ScopeFutureExt;

fn a() {
    let data = &mut [format!("Hello, ")];

    let mut future = None;
    rayon_core::scope(|s| {
        let data = &mut *data;
        future = Some(s.spawn_future(lazy(move || Ok::<_, ()>(&mut data[0]))));
    });

    // `data` is still borrowed as part of future here:
    assert_eq!(data[0], "Hello, world!"); //~ ERROR
}

fn b() {
    let data = &mut [format!("Hello, ")];

    let mut future = None;
    rayon_core::scope(|s| {
        future = Some(s.spawn_future(lazy(move || Ok::<_, ()>(&mut data[0]))));
    });

    // `data` is moved into the scope above, can't use here
    assert_eq!(data[0], "Hello, world!"); //~ ERROR
}

fn c() {
    let mut future = None;
    // borrowed value does not live long enough
    let data = &mut [format!("Hello, ")]; //~ ERROR
    rayon_core::scope(|s| {
        future = Some(s.spawn_future(lazy(move || Ok::<_, ()>(&mut data[0]))));
    });
}

fn main() { }

``` */
<commit_msg>Update the error codes for compile_fail/future_escape.rs<commit_after>/*! ```compile_fail,E0382,E0501,E0503,E0716

extern crate futures;
extern crate rayon_core;
extern crate rayon_futures;

use futures::future::lazy;
use rayon_futures::ScopeFutureExt;

fn a() {
    let data = &mut [format!("Hello, ")];

    let mut future = None;
    rayon_core::scope(|s| {
        let data = &mut *data;
        future = Some(s.spawn_future(lazy(move || Ok::<_, ()>(&mut data[0]))));
    });

    // `data` is still borrowed as part of future here:
    assert_eq!(data[0], "Hello, world!"); //~ ERROR
}

fn b() {
    let data = &mut [format!("Hello, ")];

    let mut future = None;
    rayon_core::scope(|s| {
        future = Some(s.spawn_future(lazy(move || Ok::<_, ()>(&mut data[0]))));
    });

    // `data` is moved into the scope above, can't use here
    assert_eq!(data[0], "Hello, world!"); //~ ERROR
}

fn c() {
    let mut future = None;
    // borrowed value does not live long enough
    let data = &mut [format!("Hello, ")]; //~ ERROR
    rayon_core::scope(|s| {
        future = Some(s.spawn_future(lazy(move || Ok::<_, ()>(&mut data[0]))));
    });
}

fn main() { }

``` */
<|endoftext|>


<commit_before>#[macro_use]
extern crate derive_builder;

#[derive(Debug, Clone, Builder, PartialEq, Eq)]
#[builder(build_fn(validator="LoremBuilder::validate"))]
pub struct Lorem {
    /// A percentile. Must be between 0 and 100.
    my_effort: u8,

    /// A percentile. Must be less than or equal to `Lorem::my_effort`.
    #[builder(default="40")]
    their_effort: u8,

    /// A percentile. Must be between 0 and 100.
    rivals_effort: u8,
}

impl LoremBuilder {
    /// Performs bound checks.
    fn validate(&self) -> Result<(), String> {
        if let Some(ref my_effort) = self.my_effort {
            if *my_effort > 100 {
                return Err("Don't wear yourself out".to_string());
            }
        }

        if let Some(ref their_effort) = self.their_effort {
            if *their_effort > 100 {
                return Err("The game has changed".to_string());
            }
        }

        if let Some(ref rivals_effort) = self.rivals_effort {
            if *rivals_effort > 100 {
                return Err("Your rival is cheating".to_string());
            }
        }

        Ok(())
    }
}

#[test]
fn incomplete_fields() {
    let err_msg = LoremBuilder::default().build().expect_err("Default has uninitialized fields");

    // In this case, the validator should have run but passed because there was no value set for `my_effort`.
    // Adding private `get` methods which return `Result<T, String>` by pulling in defaults will enable the
    // validation function to be improved here.
    assert!(&err_msg != "Don't wear yourself out");
}

#[test]
fn out_of_bounds() {
    assert_eq!("Don't wear yourself out", &LoremBuilder::default().my_effort(120).build().unwrap_err());
    assert_eq!("Your rival is cheating", &LoremBuilder::default().rivals_effort(120).build().unwrap_err());
}

#[test]
fn validation_pass() {
    let lorem = LoremBuilder::default()
        .my_effort(90)
        .rivals_effort(89)
        .build()
        .expect("All validations should be passing");

    assert_eq!(lorem, Lorem {
        my_effort: 90,
        rivals_effort: 89,
        their_effort: 40,
    });
}<commit_msg>Removed expect_err to build on stable<commit_after>#[macro_use]
extern crate derive_builder;

#[derive(Debug, Clone, Builder, PartialEq, Eq)]
#[builder(build_fn(validator="LoremBuilder::validate"))]
pub struct Lorem {
    /// A percentile. Must be between 0 and 100.
    my_effort: u8,

    /// A percentile. Must be less than or equal to `Lorem::my_effort`.
    #[builder(default="40")]
    their_effort: u8,

    /// A percentile. Must be between 0 and 100.
    rivals_effort: u8,
}

impl LoremBuilder {
    /// Performs bound checks.
    fn validate(&self) -> Result<(), String> {
        if let Some(ref my_effort) = self.my_effort {
            if *my_effort > 100 {
                return Err("Don't wear yourself out".to_string());
            }
        }

        if let Some(ref their_effort) = self.their_effort {
            if *their_effort > 100 {
                return Err("The game has changed".to_string());
            }
        }

        if let Some(ref rivals_effort) = self.rivals_effort {
            if *rivals_effort > 100 {
                return Err("Your rival is cheating".to_string());
            }
        }

        Ok(())
    }
}

#[test]
fn incomplete_fields() {
    let err_msg = LoremBuilder::default().build().unwrap_err();

    // In this case, the validator should have run but passed because there was no value set for `my_effort`.
    // Adding private `get` methods which return `Result<T, String>` by pulling in defaults will enable the
    // validation function to be improved here.
    assert!(&err_msg != "Don't wear yourself out");
}

#[test]
fn out_of_bounds() {
    assert_eq!("Don't wear yourself out", &LoremBuilder::default().my_effort(120).build().unwrap_err());
    assert_eq!("Your rival is cheating", &LoremBuilder::default().rivals_effort(120).build().unwrap_err());
}

#[test]
fn validation_pass() {
    let lorem = LoremBuilder::default()
        .my_effort(90)
        .rivals_effort(89)
        .build()
        .expect("All validations should be passing");

    assert_eq!(lorem, Lorem {
        my_effort: 90,
        rivals_effort: 89,
        their_effort: 40,
    });
}<|endoftext|>


<commit_before>extern crate buffering;
extern crate neli;

use buffering::StreamReadBuffer;
use neli::consts::*;
use neli::nl::NlEmpty;
use neli::nl::Nlmsghdr;
use neli::rtnl::*;
use neli::socket::*;
use neli::Nl;
use neli::MAX_NL_LENGTH;
use std::net::IpAddr;

///
/// This sample is a simple imitation of the `ip route` command, to demonstrate interaction with the rtnetlink subsystem.
///
fn main() {
    let mut socket = NlSocket::connect(NlFamily::Route, None, None, true).unwrap();

    let rtmsg : Rtmsg<Rta> = Rtmsg {
        rtm_family: libc::AF_INET as u8,
        rtm_dst_len: 0,
        rtm_src_len: 0,
        rtm_tos: 0,
        rtm_table: RtTable::Unspec,
        rtm_protocol: Rtprot::Unspec,
        rtm_scope: RtScope::Universe,
        rtm_type: Rtn::Unspec,
        rtm_flags: vec![],
        rtattrs: vec![],
    };
    let nlhdr = {
        let len = None;
        let nl_type = Rtm::Getroute;
        let flags = vec![NlmF::Request, NlmF::Root, NlmF::Match];
        let seq = None;
        let pid = None;
        let payload = rtmsg;
        Nlmsghdr::new(len, nl_type, flags, seq, pid, payload)
    };
    socket.send_nl(nlhdr).unwrap();

    'socket_read: loop {
        let mut mem = vec![0u8; MAX_NL_LENGTH];
        match socket.recv(&mut mem, 0) {
            Err(e) => {
                println!("Error: could not read from netlink socket: {}", e);
                break;
            }
            Ok(x) if x <= 0 => {
                println!("Error: could not read from netlink socket: {}", x);
                break;
            }
            Ok(read_len) => mem.truncate(read_len as usize),
        }
        let mut buf = StreamReadBuffer::new(&mem[..]);

        while !buf.at_end() {
            // Provisionally deserialize as a Nlmsg first.
            let mut nl_reader = StreamReadBuffer::new(buf.as_ref());
            let nl = Nlmsghdr::<Nlmsg, NlEmpty>::deserialize(&mut nl_reader)
                .expect("Error deserializing Nlmsghdr");
            match nl.nl_type {
                Nlmsg::Done => break 'socket_read,
                Nlmsg::Error => {
                    println!("rtnetlink error.");
                    break 'socket_read;
                }
                _ => {
                    // Some other message type, so let's try to deserialize as a Rtm.
                    let rtm = Nlmsghdr::<Rtm, Rtmsg<Rta>>::deserialize(&mut buf)
                        .expect("Error deserializing Rtmsg");

                    // This sample is only interested in the main table.
                    if rtm.nl_payload.rtm_table == RtTable::Main {
                        let mut src = None;
                        let mut dst = None;
                        let mut gateway = None;

                        for attr in &rtm.nl_payload.rtattrs {
                            fn to_addr(b: &[u8]) -> Option<IpAddr> {
                                use std::convert::TryFrom;
                                if let Ok(tup) = <&[u8; 4]>::try_from(b) {
                                    Some(IpAddr::from(tup.clone()))
                                } else if let Ok(tup) = <&[u8; 16]>::try_from(b) {
                                    Some(IpAddr::from(tup.clone()))
                                } else {
                                    None
                                }
                            }

                            match attr.rta_type {
                                Rta::Dst => dst = to_addr(&attr.rta_payload),
                                Rta::Prefsrc => src = to_addr(&attr.rta_payload),
                                Rta::Gateway => gateway = to_addr(&attr.rta_payload),
                                _ => (),
                            }
                        }

                        if let Some(dst) = dst {
                            print!("{}/{} ", dst, rtm.nl_payload.rtm_dst_len);
                        } else {
                            print!("default ");
                            if let Some(gateway) = gateway {
                                print!("via {} ", gateway);
                            }
                        }

                        if rtm.nl_payload.rtm_scope != RtScope::Universe {
                            print!(
                                " proto {:?}  scope {:?} ",
                                rtm.nl_payload.rtm_protocol, rtm.nl_payload.rtm_scope
                            )
                        }
                        if let Some(src) = src {
                            print!(" src {} ", src);
                        }
                        println!();
                    }
                }
            }
        }
    }
}
<commit_msg>Update example from skrap<commit_after>extern crate neli;

use std::error::Error;
use std::net::IpAddr;

use neli::consts::*;
use neli::err::NlError;
use neli::nl::Nlmsghdr;
use neli::rtnl::*;
use neli::socket::*;

fn parse_route_table(rtm: Nlmsghdr<Rtm, Rtmsg<Rta>>) {
    // This sample is only interested in the main table.
    if rtm.nl_payload.rtm_table == RtTable::Main {
        let mut src = None;
        let mut dst = None;
        let mut gateway = None;

        for attr in &rtm.nl_payload.rtattrs {
            fn to_addr(b: &[u8]) -> Option<IpAddr> {
                use std::convert::TryFrom;
                if let Ok(tup) = <&[u8; 4]>::try_from(b) {
                    Some(IpAddr::from(tup.clone()))
                } else if let Ok(tup) = <&[u8; 16]>::try_from(b) {
                    Some(IpAddr::from(tup.clone()))
                } else {
                    None
                }
            }

            match attr.rta_type {
                Rta::Dst => dst = to_addr(&attr.rta_payload),
                Rta::Prefsrc => src = to_addr(&attr.rta_payload),
                Rta::Gateway => gateway = to_addr(&attr.rta_payload),
                _ => (),
            }
        }

        if let Some(dst) = dst {
            print!("{}/{} ", dst, rtm.nl_payload.rtm_dst_len);
        } else {
            print!("default ");
            if let Some(gateway) = gateway {
                print!("via {} ", gateway);
            }
        }

        if rtm.nl_payload.rtm_scope != RtScope::Universe {
            print!(
                " proto {:?}  scope {:?} ",
                rtm.nl_payload.rtm_protocol, rtm.nl_payload.rtm_scope
            )
        }
        if let Some(src) = src {
            print!(" src {} ", src);
        }
        println!();
    }
}

/// This sample is a simple imitation of the `ip route` command, to demonstrate interaction
/// with the rtnetlink subsystem.
fn main() -> Result<(), Box<dyn Error>> {
    let mut socket = NlSocket::connect(NlFamily::Route, None, None, true).unwrap();

    let rtmsg : Rtmsg<Rta> = Rtmsg {
        rtm_family: Af::Inet.into(),
        rtm_dst_len: 0,
        rtm_src_len: 0,
        rtm_tos: 0,
        rtm_table: RtTable::Unspec,
        rtm_protocol: Rtprot::Unspec,
        rtm_scope: RtScope::Universe,
        rtm_type: Rtn::Unspec,
        rtm_flags: vec![],
        rtattrs: vec![],
    };
    let nlhdr = {
        let len = None;
        let nl_type = Rtm::Getroute;
        let flags = vec![NlmF::Request, NlmF::Dump];
        let seq = None;
        let pid = None;
        let payload = rtmsg;
        Nlmsghdr::new(len, nl_type, flags, seq, pid, payload)
    };
    socket.send_nl(nlhdr).unwrap();

    // Provisionally deserialize as a Nlmsg first.
    let nl = socket.recv_nl::<Rtm, Rtmsg<Rta>>(None)?;
    let multi_msg = nl.nl_flags.contains(&NlmF::Multi);
    parse_route_table(nl);
    if multi_msg {
        while let Ok(nl) = socket.recv_nl::<u16, Rtmsg<Rta>>(None) {
            match Nlmsg::from(nl.nl_type) {
                Nlmsg::Done => return Ok(()),
                Nlmsg::Error => return Err(Box::new(NlError::new("rtnetlink error."))),
                _ => {
                    let rtm = Nlmsghdr {
                        nl_len: nl.nl_len,
                        nl_type: Rtm::from(nl.nl_type),
                        nl_flags: nl.nl_flags,
                        nl_seq: nl.nl_seq,
                        nl_pid: nl.nl_pid,
                        nl_payload: nl.nl_payload,
                    };

                    // Some other message type, so let's try to deserialize as a Rtm.
                    parse_route_table(rtm)
                }
            }
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>//
// Sysinfo
//
// Copyright (c) 2017 Guillaume Gomez
//

#![crate_type = "bin"]

#![allow(unused_must_use, non_upper_case_globals)]

extern crate sysinfo;
extern crate libc;

use sysinfo::{ProcessExt, ProcessorExt, Signal, System, SystemExt};
use sysinfo::Signal::*;
use std::io::{self, BufRead};
use std::str::FromStr;
use std::io::Write;
use libc::pid_t;

const signals: [Signal; 31] = [Hangup, Interrupt, Quit, Illegal, Trap, Abort, Bus,
                               FloatingPointException, Kill, User1, Segv, User2, Pipe, Alarm,
                               Term, Stklft, Child, Continue, Stop, TSTP, TTIN, TTOU, Urgent,
                               XCPU, XFSZ, VirtualAlarm, Profiling, Winch, IO, Power, Sys];

fn print_help() {
    writeln!(&mut io::stdout(), "== Help menu ==");
    writeln!(&mut io::stdout(), "help               : show this menu");
    writeln!(&mut io::stdout(), "signals            : show the available signals");
    writeln!(&mut io::stdout(), "refresh            : reloads processes' information");
    writeln!(&mut io::stdout(), "refresh_disks      : reloads only disks' information");
    writeln!(&mut io::stdout(), "show [pid | name]  : show information of the given process \
                                 corresponding to [pid | name]");
    writeln!(&mut io::stdout(), "kill [pid] [signal]: send [signal] to the process with this \
                                 [pid]. 0 < [signal] < 32");
    writeln!(&mut io::stdout(), "proc               : Displays proc state");
    writeln!(&mut io::stdout(), "memory             : Displays memory state");
    writeln!(&mut io::stdout(), "temperature        : Displays components' temperature");
    writeln!(&mut io::stdout(), "disks              : Displays disks' information");
    writeln!(&mut io::stdout(), "all                : Displays all process name and pid");
    writeln!(&mut io::stdout(), "quit               : exit the program");
}

fn interpret_input(input: &str, sys: &mut System) -> bool {
    match input.trim() {
        "help" => print_help(),
        "refresh" => {
            writeln!(&mut io::stdout(), "Getting processus' information...");
            sys.refresh_all();
            writeln!(&mut io::stdout(), "Done.");
        }
        "refresh_disks" => {
            writeln!(&mut io::stdout(), "Refreshing disk list...");
            sys.refresh_disk_list();
            writeln!(&mut io::stdout(), "Done.");
        }
        "signals" => {
            let mut nb = 1i32;

            for sig in &signals {
                writeln!(&mut io::stdout(), "{:2}:{:?}", nb, sig);
                nb += 1;
            }
        }
        "proc" => {
            let procs = sys.get_processor_list();

            writeln!(&mut io::stdout(), "total process usage: {}%", procs[0].get_cpu_usage());
            for proc_ in procs.iter().skip(1) {
                writeln!(&mut io::stdout(), "{:?}", proc_);
            }
        }
        "memory" => {
            writeln!(&mut io::stdout(), "total memory: {} kB", sys.get_total_memory());
            writeln!(&mut io::stdout(), "used memory : {} kB", sys.get_used_memory());
            writeln!(&mut io::stdout(), "total swap  : {} kB", sys.get_total_swap());
            writeln!(&mut io::stdout(), "used swap   : {} kB", sys.get_used_swap());
        }
        "quit" | "exit" => return true,
        "all" => {
            for (pid, proc_) in sys.get_process_list() {
                writeln!(&mut io::stdout(), "{}:{} status={:?}", pid, proc_.name, proc_.status);
            }
        }
        e if e.starts_with("show ") => {
            let tmp : Vec<&str> = e.split(' ').collect();

            if tmp.len() != 2 {
                writeln!(&mut io::stdout(), "show command takes a pid or a name in parameter!");
                writeln!(&mut io::stdout(), "example: show 1254");
            } else if let Ok(pid) = pid_t::from_str(tmp[1]) {
                match sys.get_process(pid) {
                    Some(p) => writeln!(&mut io::stdout(), "{:?}", *p),
                    None => writeln!(&mut io::stdout(), "pid not found")
                };
            } else {
                let proc_name = tmp[1];
                for proc_ in sys.get_process_by_name(proc_name) {
                    writeln!(&mut io::stdout(), "==== {} ====", proc_.name);
                    writeln!(&mut io::stdout(), "{:?}", proc_);
                }
            }
        }
        "temperature" => {
            for component in sys.get_components_list() {
                writeln!(&mut io::stdout(), "{:?}", component);
            }
        }
        "show" => {
            writeln!(&mut io::stdout(), "'show' command expects a pid number or a process name");
        }
        e if e.starts_with("kill ") => {
            let tmp : Vec<&str> = e.split(' ').collect();

            if tmp.len() != 3 {
                writeln!(&mut io::stdout(),
                         "kill command takes the pid and a signal number in parameter !");
                writeln!(&mut io::stdout(), "example: kill 1254 9");
            } else {
                let pid = pid_t::from_str(tmp[1]).unwrap();
                let signal = i32::from_str(tmp[2]).unwrap();

                if signal < 1 || signal > 31 {
                    writeln!(&mut io::stdout(),
                             "Signal must be between 0 and 32 ! See the signals list with the \
                              signals command");
                } else {
                    match sys.get_process(pid) {
                        Some(p) => {
                            writeln!(&mut io::stdout(), "kill: {}",
                                     p.kill(*signals.get(signal as usize - 1).unwrap()));
                        },
                        None => {
                            writeln!(&mut io::stdout(), "pid not found");
                        }
                    };
                }
            }
        }
        "disks" => {
            for disk in sys.get_disks() {
                writeln!(&mut io::stdout(), "{:?}", disk);
            }
        }
        e => {
            writeln!(&mut io::stdout(),
                     "\"{}\": Unknown command. Enter 'help' if you want to get the commands' \
                      list.", e);
        }
    }
    false
}

fn main() {
    println!("Getting processes' information...");
    let mut t = System::new();
    println!("Done.");
    let t_stin = io::stdin();
    let mut stin = t_stin.lock();
    let mut done = false;

    println!("To get the commands' list, enter 'help'.");
    while !done {
        let mut input = String::new();
        write!(&mut io::stdout(), "> ");
        io::stdout().flush();

        stin.read_line(&mut input);
        if (&input as &str).ends_with('\n') {
            input.pop();
        }
        done = interpret_input(input.as_ref(), &mut t);
    }
}
<commit_msg>Update examples<commit_after>//
// Sysinfo
//
// Copyright (c) 2017 Guillaume Gomez
//

#![crate_type = "bin"]

#![allow(unused_must_use, non_upper_case_globals)]

extern crate sysinfo;
extern crate libc;

use sysinfo::{NetworkExt, ProcessExt, ProcessorExt, Signal, System, SystemExt};
use sysinfo::Signal::*;
use std::io::{self, BufRead};
use std::str::FromStr;
use std::io::Write;
use libc::pid_t;

const signals: [Signal; 31] = [Hangup, Interrupt, Quit, Illegal, Trap, Abort, Bus,
                               FloatingPointException, Kill, User1, Segv, User2, Pipe, Alarm,
                               Term, Stklft, Child, Continue, Stop, TSTP, TTIN, TTOU, Urgent,
                               XCPU, XFSZ, VirtualAlarm, Profiling, Winch, IO, Power, Sys];

fn print_help() {
    writeln!(&mut io::stdout(), "== Help menu ==");
    writeln!(&mut io::stdout(), "help               : show this menu");
    writeln!(&mut io::stdout(), "signals            : show the available signals");
    writeln!(&mut io::stdout(), "refresh            : reloads processes' information");
    writeln!(&mut io::stdout(), "refresh_disks      : reloads only disks' information");
    writeln!(&mut io::stdout(), "show [pid | name]  : show information of the given process \
                                 corresponding to [pid | name]");
    writeln!(&mut io::stdout(), "kill [pid] [signal]: send [signal] to the process with this \
                                 [pid]. 0 < [signal] < 32");
    writeln!(&mut io::stdout(), "proc               : Displays proc state");
    writeln!(&mut io::stdout(), "memory             : Displays memory state");
    writeln!(&mut io::stdout(), "temperature        : Displays components' temperature");
    writeln!(&mut io::stdout(), "disks              : Displays disks' information");
    writeln!(&mut io::stdout(), "network            : Displays network' information");
    writeln!(&mut io::stdout(), "all                : Displays all process name and pid");
    writeln!(&mut io::stdout(), "quit               : exit the program");
}

fn interpret_input(input: &str, sys: &mut System) -> bool {
    match input.trim() {
        "help" => print_help(),
        "refresh" => {
            writeln!(&mut io::stdout(), "Getting processus' information...");
            sys.refresh_all();
            writeln!(&mut io::stdout(), "Done.");
        }
        "refresh_disks" => {
            writeln!(&mut io::stdout(), "Refreshing disk list...");
            sys.refresh_disk_list();
            writeln!(&mut io::stdout(), "Done.");
        }
        "signals" => {
            let mut nb = 1i32;

            for sig in &signals {
                writeln!(&mut io::stdout(), "{:2}:{:?}", nb, sig);
                nb += 1;
            }
        }
        "proc" => {
            let procs = sys.get_processor_list();

            writeln!(&mut io::stdout(), "total process usage: {}%", procs[0].get_cpu_usage());
            for proc_ in procs.iter().skip(1) {
                writeln!(&mut io::stdout(), "{:?}", proc_);
            }
        }
        "memory" => {
            writeln!(&mut io::stdout(), "total memory: {} kB", sys.get_total_memory());
            writeln!(&mut io::stdout(), "used memory : {} kB", sys.get_used_memory());
            writeln!(&mut io::stdout(), "total swap  : {} kB", sys.get_total_swap());
            writeln!(&mut io::stdout(), "used swap   : {} kB", sys.get_used_swap());
        }
        "quit" | "exit" => return true,
        "all" => {
            for (pid, proc_) in sys.get_process_list() {
                writeln!(&mut io::stdout(), "{}:{} status={:?}", pid, proc_.name, proc_.status);
            }
        }
        e if e.starts_with("show ") => {
            let tmp : Vec<&str> = e.split(' ').collect();

            if tmp.len() != 2 {
                writeln!(&mut io::stdout(), "show command takes a pid or a name in parameter!");
                writeln!(&mut io::stdout(), "example: show 1254");
            } else if let Ok(pid) = pid_t::from_str(tmp[1]) {
                match sys.get_process(pid) {
                    Some(p) => writeln!(&mut io::stdout(), "{:?}", *p),
                    None => writeln!(&mut io::stdout(), "pid not found")
                };
            } else {
                let proc_name = tmp[1];
                for proc_ in sys.get_process_by_name(proc_name) {
                    writeln!(&mut io::stdout(), "==== {} ====", proc_.name);
                    writeln!(&mut io::stdout(), "{:?}", proc_);
                }
            }
        }
        "temperature" => {
            for component in sys.get_components_list() {
                writeln!(&mut io::stdout(), "{:?}", component);
            }
        }
        "network" => {
            writeln!(&mut io::stdout(), "input data : {} B", sys.get_network().get_income());
            writeln!(&mut io::stdout(), "output data: {} B", sys.get_network().get_outcome());
        }
        "show" => {
            writeln!(&mut io::stdout(), "'show' command expects a pid number or a process name");
        }
        e if e.starts_with("kill ") => {
            let tmp : Vec<&str> = e.split(' ').collect();

            if tmp.len() != 3 {
                writeln!(&mut io::stdout(),
                         "kill command takes the pid and a signal number in parameter !");
                writeln!(&mut io::stdout(), "example: kill 1254 9");
            } else {
                let pid = pid_t::from_str(tmp[1]).unwrap();
                let signal = i32::from_str(tmp[2]).unwrap();

                if signal < 1 || signal > 31 {
                    writeln!(&mut io::stdout(),
                             "Signal must be between 0 and 32 ! See the signals list with the \
                              signals command");
                } else {
                    match sys.get_process(pid) {
                        Some(p) => {
                            writeln!(&mut io::stdout(), "kill: {}",
                                     p.kill(*signals.get(signal as usize - 1).unwrap()));
                        },
                        None => {
                            writeln!(&mut io::stdout(), "pid not found");
                        }
                    };
                }
            }
        }
        "disks" => {
            for disk in sys.get_disks() {
                writeln!(&mut io::stdout(), "{:?}", disk);
            }
        }
        e => {
            writeln!(&mut io::stdout(),
                     "\"{}\": Unknown command. Enter 'help' if you want to get the commands' \
                      list.", e);
        }
    }
    false
}

fn main() {
    println!("Getting processes' information...");
    let mut t = System::new();
    println!("Done.");
    let t_stin = io::stdin();
    let mut stin = t_stin.lock();
    let mut done = false;

    println!("To get the commands' list, enter 'help'.");
    while !done {
        let mut input = String::new();
        write!(&mut io::stdout(), "> ");
        io::stdout().flush();

        stin.read_line(&mut input);
        if (&input as &str).ends_with('\n') {
            input.pop();
        }
        done = interpret_input(input.as_ref(), &mut t);
    }
}
<|endoftext|>