<commit_before>//! A test suite for `-Zbuild-std` which is much more expensive than the
//! standard test suite.
//!
//! This test suite attempts to perform a full integration test where we
//! actually compile the standard library from source (like the real one) and
//! the various tests associated with that.
//!
//! YOU SHOULD IDEALLY NOT WRITE TESTS HERE.
//!
//! If possible, use `tests/testsuite/standard_lib.rs` instead. That uses a
//! 'mock' sysroot which is much faster to compile. The tests here are
//! extremely intensive and are only intended to run on CI and are theoretically
//! not catching any regressions that `tests/testsuite/standard_lib.rs` isn't
//! already catching.
//!
//! All tests here should use `#[cargo_test(build_std)]` to indicate that
//! boilerplate should be generated to require the nightly toolchain and the
//! `CARGO_RUN_BUILD_STD_TESTS` env var to be set to actually run these tests.
//! Otherwise the tests are skipped.

use cargo_test_support::*;
use std::env;
use std::path::Path;

fn enable_build_std(e: &mut Execs, arg: Option<&str>) {
    e.env_remove("CARGO_HOME");
    e.env_remove("HOME");
    e.arg("-Zno-index-update");

    // And finally actually enable `build-std` for now
    let arg = match arg {
        Some(s) => format!("-Zbuild-std={}", s),
        None => "-Zbuild-std".to_string(),
    };
    e.arg(arg);
    e.masquerade_as_nightly_cargo();
}

// Helper methods used in the tests below
trait BuildStd: Sized {
    fn build_std(&mut self) -> &mut Self;
    fn build_std_arg(&mut self, arg: &str) -> &mut Self;
    fn target_host(&mut self) -> &mut Self;
}

impl BuildStd for Execs {
    fn build_std(&mut self) -> &mut Self {
        enable_build_std(self, None);
        self
    }

    fn build_std_arg(&mut self, arg: &str) -> &mut Self {
        enable_build_std(self, Some(arg));
        self
    }

    fn target_host(&mut self) -> &mut Self {
        self.arg("--target").arg(rustc_host());
        self
    }
}

#[cargo_test(build_std)]
fn basic() {
    let p = project()
        .file(
            "src/main.rs",
            "
                fn main() {
                    foo::f();
                }

                #[test]
                fn smoke_bin_unit() {
                    foo::f();
                }
            ",
        )
        .file(
            "src/lib.rs",
            "
                extern crate alloc;
                extern crate proc_macro;

                /// ```
                /// foo::f();
                /// ```
                pub fn f() {
                }

                #[test]
                fn smoke_lib_unit() {
                    f();
                }
            ",
        )
        .file(
            "tests/smoke.rs",
            "
                #[test]
                fn smoke_integration() {
                    foo::f();
                }
            ",
        )
        .build();

    p.cargo("check").build_std().target_host().run();
    p.cargo("build").build_std().target_host().run();
    p.cargo("run").build_std().target_host().run();
    p.cargo("test").build_std().target_host().run();
}

#[cargo_test(build_std)]
fn cross_custom() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.1.0"
                edition = "2018"

                [target.custom-target.dependencies]
                dep = { path = "dep" }
            "#,
        )
        .file(
            "src/lib.rs",
            "#![no_std] pub fn f() -> u32 { dep::answer() }",
        )
        .file("dep/Cargo.toml", &basic_manifest("dep", "0.1.0"))
        .file("dep/src/lib.rs", "#![no_std] pub fn answer() -> u32 { 42 }")
        .file(
            "custom-target.json",
            r#"
            {
                "llvm-target": "x86_64-unknown-none-gnu",
                "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
                "arch": "x86_64",
                "target-endian": "little",
                "target-pointer-width": "64",
                "target-c-int-width": "32",
                "os": "none",
                "linker-flavor": "ld.lld"
            }
            "#,
        )
        .build();

    p.cargo("build --target custom-target.json -v")
        .build_std_arg("core")
        .run();
}

#[cargo_test(build_std)]
fn custom_test_framework() {
    let p = project()
        .file(
            "src/lib.rs",
            r#"
            #![no_std]
            #![cfg_attr(test, no_main)]
            #![feature(custom_test_frameworks)]
            #![test_runner(crate::test_runner)]

            pub fn test_runner(_tests: &[&dyn Fn()]) {}

            #[panic_handler]
            fn panic(_info: &core::panic::PanicInfo) -> ! {
                loop {}
            }
            "#,
        )
        .file(
            "target.json",
            r#"
            {
                "llvm-target": "x86_64-unknown-none-gnu",
                "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
                "arch": "x86_64",
                "target-endian": "little",
                "target-pointer-width": "64",
                "target-c-int-width": "32",
                "os": "none",
                "linker-flavor": "ld.lld",
                "linker": "rust-lld",
                "executables": true,
                "panic-strategy": "abort"
            }
            "#,
        )
        .build();

    // This is a bit of a hack to use the rust-lld that ships with most toolchains.
    let sysroot = paths::sysroot();
    let sysroot = Path::new(&sysroot);
    let sysroot_bin = sysroot
        .join("lib")
        .join("rustlib")
        .join(rustc_host())
        .join("bin");
    let path = env::var_os("PATH").unwrap_or_default();
    let mut paths = env::split_paths(&path).collect::<Vec<_>>();
    paths.insert(0, sysroot_bin);
    let new_path = env::join_paths(paths).unwrap();

    p.cargo("test --target target.json --no-run -v")
        .env("PATH", new_path)
        .build_std_arg("core")
        .run();
}

#[cargo_test(build_std)]
fn common_crate_collision() {
    // Check for collision with `cc` crate in build dependencies.
    // This needs to be a full test since we need to use the real `cc` crate.
    // This is a bit fragile, since it assumes `cc` is used in libstd,
    // and that we are selecting the same features.

    // Determine the version of CC used in the real std so that we use the
    // exact same version.
    let sysroot = paths::sysroot();
    let sysroot = Path::new(&sysroot);
    let contents =
        std::fs::read_to_string(sysroot.join("lib/rustlib/src/rust/Cargo.lock")).unwrap();
    let lock: toml::Value = toml::from_str(&contents).unwrap();
    let mut packages = lock["package"].as_array().unwrap().iter();
    let cc = packages
        .find(|p| p["name"].as_str().unwrap() == "cc")
        .unwrap();
    // Make sure there is only one `cc`.
    assert!(packages
        .find(|p| p["name"].as_str().unwrap() == "cc")
        .is_none());
    let cc_version = cc["version"].as_str().unwrap();

    let p = project()
        .file(
            "Cargo.toml",
            &format!(
                r#"
                [package]
                name = "foo"
                version = "0.1.0"

                [build-dependencies]
                cc = "={}"
                "#,
                cc_version
            ),
        )
        .file("build.rs", "extern crate cc; fn main() {}")
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build -v")
        .build_std()
        .target_host()
        .with_stderr_contains(
            "[RUNNING] `rustc --crate-name cc [..]-Zforce-unstable-if-unmarked[..]",
        )
        .with_stderr_line_without(
            &["[RUNNING] `rustc --crate-name cc"],
            &["-Zforce-unstable-if-unmarked"],
        )
        .run();
}
<commit_msg>Remove likely brittle test.<commit_after>//! A test suite for `-Zbuild-std` which is much more expensive than the
//! standard test suite.
//!
//! This test suite attempts to perform a full integration test where we
//! actually compile the standard library from source (like the real one) and
//! the various tests associated with that.
//!
//! YOU SHOULD IDEALLY NOT WRITE TESTS HERE.
//!
//! If possible, use `tests/testsuite/standard_lib.rs` instead. That uses a
//! 'mock' sysroot which is much faster to compile. The tests here are
//! extremely intensive and are only intended to run on CI and are theoretically
//! not catching any regressions that `tests/testsuite/standard_lib.rs` isn't
//! already catching.
//!
//! All tests here should use `#[cargo_test(build_std)]` to indicate that
//! boilerplate should be generated to require the nightly toolchain and the
//! `CARGO_RUN_BUILD_STD_TESTS` env var to be set to actually run these tests.
//! Otherwise the tests are skipped.

use cargo_test_support::*;
use std::env;
use std::path::Path;

fn enable_build_std(e: &mut Execs, arg: Option<&str>) {
    e.env_remove("CARGO_HOME");
    e.env_remove("HOME");
    e.arg("-Zno-index-update");

    // And finally actually enable `build-std` for now
    let arg = match arg {
        Some(s) => format!("-Zbuild-std={}", s),
        None => "-Zbuild-std".to_string(),
    };
    e.arg(arg);
    e.masquerade_as_nightly_cargo();
}

// Helper methods used in the tests below
trait BuildStd: Sized {
    fn build_std(&mut self) -> &mut Self;
    fn build_std_arg(&mut self, arg: &str) -> &mut Self;
    fn target_host(&mut self) -> &mut Self;
}

impl BuildStd for Execs {
    fn build_std(&mut self) -> &mut Self {
        enable_build_std(self, None);
        self
    }

    fn build_std_arg(&mut self, arg: &str) -> &mut Self {
        enable_build_std(self, Some(arg));
        self
    }

    fn target_host(&mut self) -> &mut Self {
        self.arg("--target").arg(rustc_host());
        self
    }
}

#[cargo_test(build_std)]
fn basic() {
    let p = project()
        .file(
            "src/main.rs",
            "
                fn main() {
                    foo::f();
                }

                #[test]
                fn smoke_bin_unit() {
                    foo::f();
                }
            ",
        )
        .file(
            "src/lib.rs",
            "
                extern crate alloc;
                extern crate proc_macro;

                /// ```
                /// foo::f();
                /// ```
                pub fn f() {
                }

                #[test]
                fn smoke_lib_unit() {
                    f();
                }
            ",
        )
        .file(
            "tests/smoke.rs",
            "
                #[test]
                fn smoke_integration() {
                    foo::f();
                }
            ",
        )
        .build();

    p.cargo("check").build_std().target_host().run();
    p.cargo("build").build_std().target_host().run();
    p.cargo("run").build_std().target_host().run();
    p.cargo("test").build_std().target_host().run();
}

#[cargo_test(build_std)]
fn cross_custom() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.1.0"
                edition = "2018"

                [target.custom-target.dependencies]
                dep = { path = "dep" }
            "#,
        )
        .file(
            "src/lib.rs",
            "#![no_std] pub fn f() -> u32 { dep::answer() }",
        )
        .file("dep/Cargo.toml", &basic_manifest("dep", "0.1.0"))
        .file("dep/src/lib.rs", "#![no_std] pub fn answer() -> u32 { 42 }")
        .file(
            "custom-target.json",
            r#"
            {
                "llvm-target": "x86_64-unknown-none-gnu",
                "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
                "arch": "x86_64",
                "target-endian": "little",
                "target-pointer-width": "64",
                "target-c-int-width": "32",
                "os": "none",
                "linker-flavor": "ld.lld"
            }
            "#,
        )
        .build();

    p.cargo("build --target custom-target.json -v")
        .build_std_arg("core")
        .run();
}

#[cargo_test(build_std)]
fn custom_test_framework() {
    let p = project()
        .file(
            "src/lib.rs",
            r#"
            #![no_std]
            #![cfg_attr(test, no_main)]
            #![feature(custom_test_frameworks)]
            #![test_runner(crate::test_runner)]

            pub fn test_runner(_tests: &[&dyn Fn()]) {}

            #[panic_handler]
            fn panic(_info: &core::panic::PanicInfo) -> ! {
                loop {}
            }
            "#,
        )
        .file(
            "target.json",
            r#"
            {
                "llvm-target": "x86_64-unknown-none-gnu",
                "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
                "arch": "x86_64",
                "target-endian": "little",
                "target-pointer-width": "64",
                "target-c-int-width": "32",
                "os": "none",
                "linker-flavor": "ld.lld",
                "linker": "rust-lld",
                "executables": true,
                "panic-strategy": "abort"
            }
            "#,
        )
        .build();

    // This is a bit of a hack to use the rust-lld that ships with most toolchains.
    let sysroot = paths::sysroot();
    let sysroot = Path::new(&sysroot);
    let sysroot_bin = sysroot
        .join("lib")
        .join("rustlib")
        .join(rustc_host())
        .join("bin");
    let path = env::var_os("PATH").unwrap_or_default();
    let mut paths = env::split_paths(&path).collect::<Vec<_>>();
    paths.insert(0, sysroot_bin);
    let new_path = env::join_paths(paths).unwrap();

    p.cargo("test --target target.json --no-run -v")
        .env("PATH", new_path)
        .build_std_arg("core")
        .run();
}
<|endoftext|>


<commit_before>/*
 * Steps of XWayland server creation
 *
 * Sockets to create:
 * - a pair for XWayland to connect to smithay as a wayland client, we use our
 *   end to insert the XWayland client in the display
 * - a pair for smithay to connect to XWayland as a WM, we give our end to the
 *   WM and it deals with it
 * - 2 listening sockets on which the XWayland server will listen. We need to
 *   bind them ourselves so we know what value put in the $DISPLAY env variable.
 *   This involves some dance with a lockfile to ensure there is no collision with
 *   an other starting xserver
 *   if we listen on display $D, their paths are respectively:
 *   - /tmp/.X11-unix/X$D
 *   - @/tmp/.X11-unix/X$D (abstract socket)
 *
 * The XWayland server is spawned via fork+exec.
 * -> wlroots does a double-fork while weston a single one, why ??
 *    -> https://stackoverflow.com/questions/881388/
 * -> once it is started, it sends us a SIGUSR1, we need to setup a listener
 *    for it and when we receive it we can launch the WM
 * -> we need to track if the XWayland crashes, to restart it
 *
 * cf https://github.com/swaywm/wlroots/blob/master/xwayland/xwayland.c
 *
 */
use std::{
    any::Any,
    cell::RefCell,
    env,
    ffi::CString,
    os::unix::{
        io::{AsRawFd, IntoRawFd},
        net::UnixStream,
    },
    rc::Rc,
    sync::Arc,
};

use calloop::{
    signals::{Signal, Signals},
    LoopHandle, Source,
};

use nix::{
    errno::Errno,
    sys::signal,
    unistd::{fork, ForkResult, Pid},
    Error as NixError, Result as NixResult,
};

use wayland_server::{Client, Display, Filter};

use super::x11_sockets::{prepare_x11_sockets, X11Lock};

/// The XWayland handle
pub struct XWayland<WM: XWindowManager> {
    inner: Rc<RefCell<Inner<WM>>>,
}

/// Trait to be implemented by you WM for XWayland
///
/// This is a very low-level trait, only notifying you
/// when the connection with XWayland is up, or when
/// it terminates.
///
/// You WM must be able handle the XWayland server connecting
/// then disconnecting several time in a row, but only a single
/// connection will be active at any given time.
pub trait XWindowManager {
    /// The XWayland server is ready
    ///
    /// Your privileged connection to it is this `UnixStream`
    fn xwayland_ready(&mut self, connection: UnixStream, client: Client);
    /// The XWayland server has exited
    fn xwayland_exited(&mut self);
}

impl<WM: XWindowManager + 'static> XWayland<WM> {
    /// Start the XWayland server
    pub fn init<L, T: Any, Data: 'static>(
        wm: WM,
        handle: LoopHandle<Data>,
        display: Rc<RefCell<Display>>,
        data: &mut T,
        logger: L,
    ) -> Result<XWayland<WM>, ()>
    where
        L: Into<Option<::slog::Logger>>,
    {
        let log = crate::slog_or_fallback(logger);
        let inner = Rc::new(RefCell::new(Inner {
            wm,
            kill_source: {
                let handle = handle.clone();
                Box::new(move |source| handle.kill(source))
            },
            source_maker: Box::new(move |inner| {
                handle
                    .insert_source(
                        Signals::new(&[Signal::SIGUSR1]).map_err(|_| ())?,
                        move |evt, _, _| {
                            debug_assert!(evt.signal() == Signal::SIGUSR1);
                            xwayland_ready(&inner);
                        },
                    )
                    .map_err(|_| ())
            }),
            wayland_display: display,
            instance: None,
            log: log.new(o!("smithay_module" => "XWayland")),
        }));
        launch(&inner, data)?;
        Ok(XWayland { inner })
    }
}

impl<WM: XWindowManager> Drop for XWayland<WM> {
    fn drop(&mut self) {
        self.inner.borrow_mut().shutdown();
    }
}

struct XWaylandInstance {
    display_lock: X11Lock,
    wayland_client: Client,
    sigusr1_handler: Option<Source<Signals>>,
    wm_fd: Option<UnixStream>,
    started_at: ::std::time::Instant,
    child_pid: Option<Pid>,
}

type SourceMaker<WM> = dyn FnMut(Rc<RefCell<Inner<WM>>>) -> Result<Source<Signals>, ()>;

// Inner implementation of the XWayland manager
struct Inner<WM: XWindowManager> {
    wm: WM,
    source_maker: Box<SourceMaker<WM>>,
    wayland_display: Rc<RefCell<Display>>,
    instance: Option<XWaylandInstance>,
    kill_source: Box<dyn Fn(Source<Signals>)>,
    log: ::slog::Logger,
}

// Launch an XWayland server
//
// Does nothing if there is already a launched instance
fn launch<WM: XWindowManager + 'static, T: Any>(
    inner: &Rc<RefCell<Inner<WM>>>,
    data: &mut T,
) -> Result<(), ()> {
    let mut guard = inner.borrow_mut();
    if guard.instance.is_some() {
        return Ok(());
    }

    info!(guard.log, "Starting XWayland");

    let (x_wm_x11, x_wm_me) = UnixStream::pair().map_err(|_| ())?;
    let (wl_x11, wl_me) = UnixStream::pair().map_err(|_| ())?;

    let (lock, x_fds) = prepare_x11_sockets(guard.log.clone())?;

    // we have now created all the required sockets

    // record launch time
    let creation_time = ::std::time::Instant::now();

    // create the wayland client for XWayland
    let client = unsafe {
        guard
            .wayland_display
            .borrow_mut()
            .create_client(wl_me.into_raw_fd(), data)
    };
    client.data_map().insert_if_missing(|| inner.clone());
    client.add_destructor(Filter::new(|e: Arc<_>, _, mut data| {
        client_destroy::<WM, T>(&e, data.get().unwrap())
    }));

    // setup the SIGUSR1 handler
    let sigusr1_handler = (&mut *guard.source_maker)(inner.clone())?;

    // all is ready, we can do the fork dance
    let child_pid = match unsafe { fork() } {
        Ok(ForkResult::Parent { child }) => {
            // we are the main smithay process
            child
        }
        Ok(ForkResult::Child) => {
            // we are the first child
            let ppid = Pid::parent();
            let mut set = signal::SigSet::empty();
            set.add(signal::Signal::SIGUSR1);
            set.add(signal::Signal::SIGCHLD);
            // we can't handle errors here anyway
            let _ = signal::sigprocmask(signal::SigmaskHow::SIG_BLOCK, Some(&set), None);
            match unsafe { fork() } {
                Ok(ForkResult::Parent { child }) => {
                    // we are still the first child
                    let sig = set.wait();
                    // send USR1 to parent
                    let _ = signal::kill(ppid, signal::Signal::SIGUSR1);
                    // Parent will wait for us and know from out
                    // exit status if XWayland launch was a success or not =)
                    if let Ok(signal::Signal::SIGCHLD) = sig {
                        // XWayland has exited before being ready
                        let _ = ::nix::sys::wait::waitpid(child, None);
                        unsafe { ::nix::libc::exit(1) };
                    }
                    unsafe { ::nix::libc::exit(0) };
                }
                Ok(ForkResult::Child) => {
                    // we are the second child, we exec xwayland
                    match exec_xwayland(lock.display(), wl_x11, x_wm_x11, &x_fds) {
                        Ok(x) => match x {},
                        Err(e) => {
                            // well, what can we do ?
                            error!(guard.log, "exec XWayland failed"; "err" => format!("{:?}", e));
                            unsafe { ::nix::libc::exit(1) };
                        }
                    }
                }
                Err(e) => {
                    // well, what can we do ?
                    error!(guard.log, "XWayland second fork failed"; "err" => format!("{:?}", e));
                    unsafe { ::nix::libc::exit(1) };
                }
            }
        }
        Err(e) => {
            error!(guard.log, "XWayland first fork failed"; "err" => format!("{:?}", e));
            return Err(());
        }
    };

    guard.instance = Some(XWaylandInstance {
        display_lock: lock,
        wayland_client: client,
        sigusr1_handler: Some(sigusr1_handler),
        wm_fd: Some(x_wm_me),
        started_at: creation_time,
        child_pid: Some(child_pid),
    });

    Ok(())
}

impl<WM: XWindowManager> Inner<WM> {
    // Shutdown the XWayland server and cleanup everything
    fn shutdown(&mut self) {
        // don't do anything if not running
        if let Some(mut instance) = self.instance.take() {
            info!(self.log, "Shutting down XWayland.");
            self.wm.xwayland_exited();
            // kill the client
            instance.wayland_client.kill();
            // remove the event source
            if let Some(s) = instance.sigusr1_handler.take() {
                (self.kill_source)(s);
            }
            // All connections and lockfiles are cleaned by their destructors

            // Remove DISPLAY from the env
            ::std::env::remove_var("DISPLAY");
            // We do like wlroots:
            // > We do not kill the XWayland process, it dies to broken pipe
            // > after we close our side of the wm/wl fds. This is more reliable
            // > than trying to kill something that might no longer be XWayland.
        }
    }
}

fn client_destroy<WM: XWindowManager + 'static, T: Any>(map: &::wayland_server::UserDataMap, data: &mut T) {
    let inner = map.get::<Rc<RefCell<Inner<WM>>>>().unwrap();

    // shutdown the server
    let started_at = inner.borrow().instance.as_ref().map(|i| i.started_at);
    inner.borrow_mut().shutdown();

    // restart it, unless we really just started it, if it crashes right
    // at startup there is no point
    if started_at.map(|t| t.elapsed().as_secs()).unwrap_or(10) > 5 {
        warn!(inner.borrow().log, "XWayland crashed, restarting.");
        let _ = launch(&inner, data);
    } else {
        warn!(
            inner.borrow().log,
            "XWayland crashed less than 5 seconds after its startup, not restarting."
        );
    }
}

fn xwayland_ready<WM: XWindowManager>(inner: &Rc<RefCell<Inner<WM>>>) {
    use nix::sys::wait;
    let mut guard = inner.borrow_mut();
    let inner = &mut *guard;
    // instance should never be None at this point
    let instance = inner.instance.as_mut().unwrap();
    let wm = &mut inner.wm;
    // neither the pid
    let pid = instance.child_pid.unwrap();

    // find out if the launch was a success by waiting on the intermediate child
    let success: bool;
    loop {
        match wait::waitpid(pid, None) {
            Ok(wait::WaitStatus::Exited(_, 0)) => {
                // XWayland was correctly started :)
                success = true;
                break;
            }
            Err(NixError::Sys(Errno::EINTR)) => {
                // interupted, retry
                continue;
            }
            _ => {
                // something went wrong :(
                success = false;
                break;
            }
        }
    }

    if success {
        // signal the WM
        info!(inner.log, "XWayland is ready, signaling the WM.");
        wm.xwayland_ready(
            instance.wm_fd.take().unwrap(), // This is a bug if None
            instance.wayland_client.clone(),
        );

        // setup the environemnt
        ::std::env::set_var("DISPLAY", format!(":{}", instance.display_lock.display()));
    } else {
        error!(
            inner.log,
            "XWayland crashed at startup, will not try to restart it."
        );
    }

    // in all cases, cleanup
    if let Some(s) = instance.sigusr1_handler.take() {
        (inner.kill_source)(s);
    }
}

enum Void {}

/// Exec XWayland with given sockets on given display
///
/// If this returns, that means that something failed
fn exec_xwayland(
    display: u32,
    wayland_socket: UnixStream,
    wm_socket: UnixStream,
    listen_sockets: &[UnixStream],
) -> NixResult<Void> {
    // uset the CLOEXEC flag from the sockets we need to pass
    // to xwayland
    unset_cloexec(&wayland_socket)?;
    unset_cloexec(&wm_socket)?;
    for socket in listen_sockets {
        unset_cloexec(socket)?;
    }
    // prepare the arguments to XWayland
    let mut args = vec![
        CString::new("Xwayland").unwrap(),
        CString::new(format!(":{}", display)).unwrap(),
        CString::new("-rootless").unwrap(),
        CString::new("-terminate").unwrap(),
        CString::new("-wm").unwrap(),
        CString::new(format!("{}", wm_socket.as_raw_fd())).unwrap(),
    ];
    for socket in listen_sockets {
        args.push(CString::new("-listen").unwrap());
        args.push(CString::new(format!("{}", socket.as_raw_fd())).unwrap());
    }
    // setup the environment: clear everything except PATH and XDG_RUNTIME_DIR
    for (key, _) in env::vars_os() {
        if key.to_str() == Some("PATH") || key.to_str() == Some("XDG_RUNTIME_DIR") {
            continue;
        }
        env::remove_var(key);
    }
    // the WAYLAND_SOCKET var tells XWayland where to connect as a wayland client
    env::set_var("WAYLAND_SOCKET", format!("{}", wayland_socket.as_raw_fd()));

    // ignore SIGUSR1, this will make the XWayland server send us this
    // signal when it is ready apparently
    unsafe {
        use nix::sys::signal::*;
        sigaction(
            Signal::SIGUSR1,
            &SigAction::new(SigHandler::SigIgn, SaFlags::empty(), SigSet::empty()),
        )?;
    }

    // run it
    let ret = ::nix::unistd::execvp(
        &CString::new("Xwayland").unwrap(),
        &args.iter().map(AsRef::as_ref).collect::<Vec<_>>(),
    )?;
    // small dance to actually return Void
    match ret {}
}

/// Remove the `O_CLOEXEC` flag from this `Fd`
///
/// This means that the `Fd` will *not* be automatically
/// closed when we `exec()` into XWayland
fn unset_cloexec<F: AsRawFd>(fd: &F) -> NixResult<()> {
    use nix::fcntl::{fcntl, FcntlArg, FdFlag};
    fcntl(fd.as_raw_fd(), FcntlArg::F_SETFD(FdFlag::empty()))?;
    Ok(())
}
<commit_msg>xwayland: Use pipe instead of signal<commit_after>/*
 * Steps of XWayland server creation
 *
 * Sockets to create:
 * - a pair for XWayland to connect to smithay as a wayland client, we use our
 *   end to insert the XWayland client in the display
 * - a pair for smithay to connect to XWayland as a WM, we give our end to the
 *   WM and it deals with it
 * - 2 listening sockets on which the XWayland server will listen. We need to
 *   bind them ourselves so we know what value put in the $DISPLAY env variable.
 *   This involves some dance with a lockfile to ensure there is no collision with
 *   an other starting xserver
 *   if we listen on display $D, their paths are respectively:
 *   - /tmp/.X11-unix/X$D
 *   - @/tmp/.X11-unix/X$D (abstract socket)
 *
 * The XWayland server is spawned via fork+exec.
 * -> wlroots does a double-fork while weston a single one, why ??
 *    -> https://stackoverflow.com/questions/881388/
 * -> once it is started, it sends us a SIGUSR1, we need to setup a listener
 *    for it and when we receive it we can launch the WM
 * -> we need to track if the XWayland crashes, to restart it
 *
 * cf https://github.com/swaywm/wlroots/blob/master/xwayland/xwayland.c
 *
 */
use std::{
    any::Any,
    cell::RefCell,
    env,
    ffi::CString,
    os::unix::{
        io::{AsRawFd, IntoRawFd},
        net::UnixStream,
    },
    rc::Rc,
    sync::Arc,
};

use calloop::{generic::Generic, Interest, LoopHandle, Mode, Source};

use nix::{
    errno::Errno,
    sys::signal,
    unistd::{fork, ForkResult, Pid},
    Error as NixError, Result as NixResult,
};

use wayland_server::{Client, Display, Filter};

use super::x11_sockets::{prepare_x11_sockets, X11Lock};

/// The XWayland handle
pub struct XWayland<WM: XWindowManager> {
    inner: Rc<RefCell<Inner<WM>>>,
}

/// Trait to be implemented by you WM for XWayland
///
/// This is a very low-level trait, only notifying you
/// when the connection with XWayland is up, or when
/// it terminates.
///
/// You WM must be able handle the XWayland server connecting
/// then disconnecting several time in a row, but only a single
/// connection will be active at any given time.
pub trait XWindowManager {
    /// The XWayland server is ready
    ///
    /// Your privileged connection to it is this `UnixStream`
    fn xwayland_ready(&mut self, connection: UnixStream, client: Client);
    /// The XWayland server has exited
    fn xwayland_exited(&mut self);
}

impl<WM: XWindowManager + 'static> XWayland<WM> {
    /// Start the XWayland server
    pub fn init<L, T: Any, Data: 'static>(
        wm: WM,
        handle: LoopHandle<Data>,
        display: Rc<RefCell<Display>>,
        data: &mut T,
        logger: L,
    ) -> Result<XWayland<WM>, ()>
    where
        L: Into<Option<::slog::Logger>>,
    {
        let log = crate::slog_or_fallback(logger);
        let inner = Rc::new(RefCell::new(Inner {
            wm,
            kill_source: {
                let handle = handle.clone();
                Box::new(move |source| handle.kill(source))
            },
            source_maker: Box::new(move |inner, fd| {
                handle
                    .insert_source(
                        Generic::new(fd, Interest::Readable, Mode::Level),
                        move |evt, _, _| {
                            debug_assert!(evt.readable);
                            xwayland_ready(&inner);
                            Ok(())
                        },
                    )
                    .map_err(|_| ())
            }),
            wayland_display: display,
            instance: None,
            log: log.new(o!("smithay_module" => "XWayland")),
        }));
        launch(&inner, data)?;
        Ok(XWayland { inner })
    }
}

impl<WM: XWindowManager> Drop for XWayland<WM> {
    fn drop(&mut self) {
        self.inner.borrow_mut().shutdown();
    }
}

struct XWaylandInstance {
    display_lock: X11Lock,
    wayland_client: Client,
    startup_handler: Option<Source<Generic<UnixStream>>>,
    wm_fd: Option<UnixStream>,
    started_at: ::std::time::Instant,
    child_pid: Option<Pid>,
}

type SourceMaker<WM> =
    dyn FnMut(Rc<RefCell<Inner<WM>>>, UnixStream) -> Result<Source<Generic<UnixStream>>, ()>;

// Inner implementation of the XWayland manager
struct Inner<WM: XWindowManager> {
    wm: WM,
    source_maker: Box<SourceMaker<WM>>,
    wayland_display: Rc<RefCell<Display>>,
    instance: Option<XWaylandInstance>,
    kill_source: Box<dyn Fn(Source<Generic<UnixStream>>)>,
    log: ::slog::Logger,
}

// Launch an XWayland server
//
// Does nothing if there is already a launched instance
fn launch<WM: XWindowManager + 'static, T: Any>(
    inner: &Rc<RefCell<Inner<WM>>>,
    data: &mut T,
) -> Result<(), ()> {
    let mut guard = inner.borrow_mut();
    if guard.instance.is_some() {
        return Ok(());
    }

    info!(guard.log, "Starting XWayland");

    let (status_child, status_me) = UnixStream::pair().map_err(|_| ())?;
    let (x_wm_x11, x_wm_me) = UnixStream::pair().map_err(|_| ())?;
    let (wl_x11, wl_me) = UnixStream::pair().map_err(|_| ())?;

    let (lock, x_fds) = prepare_x11_sockets(guard.log.clone())?;

    // we have now created all the required sockets

    // record launch time
    let creation_time = ::std::time::Instant::now();

    // create the wayland client for XWayland
    let client = unsafe {
        guard
            .wayland_display
            .borrow_mut()
            .create_client(wl_me.into_raw_fd(), data)
    };
    client.data_map().insert_if_missing(|| inner.clone());
    client.add_destructor(Filter::new(|e: Arc<_>, _, mut data| {
        client_destroy::<WM, T>(&e, data.get().unwrap())
    }));

    // all is ready, we can do the fork dance
    let child_pid = match unsafe { fork() } {
        Ok(ForkResult::Parent { child }) => {
            // we are the main smithay process
            child
        }
        Ok(ForkResult::Child) => {
            // we are the first child
            let mut set = signal::SigSet::empty();
            set.add(signal::Signal::SIGUSR1);
            set.add(signal::Signal::SIGCHLD);
            // we can't handle errors here anyway
            let _ = signal::sigprocmask(signal::SigmaskHow::SIG_BLOCK, Some(&set), None);
            match unsafe { fork() } {
                Ok(ForkResult::Parent { child }) => {
                    // When we exit(), we will close() this which wakes up the main process.
                    let _status_child = status_child;
                    // we are still the first child
                    let sig = set.wait();
                    // Parent will wait for us and know from out
                    // exit status if XWayland launch was a success or not =)
                    if let Ok(signal::Signal::SIGCHLD) = sig {
                        // XWayland has exited before being ready
                        let _ = ::nix::sys::wait::waitpid(child, None);
                        unsafe { ::nix::libc::exit(1) };
                    }
                    unsafe { ::nix::libc::exit(0) };
                }
                Ok(ForkResult::Child) => {
                    // we are the second child, we exec xwayland
                    match exec_xwayland(lock.display(), wl_x11, x_wm_x11, &x_fds) {
                        Ok(x) => match x {},
                        Err(e) => {
                            // well, what can we do ?
                            error!(guard.log, "exec XWayland failed"; "err" => format!("{:?}", e));
                            unsafe { ::nix::libc::exit(1) };
                        }
                    }
                }
                Err(e) => {
                    // well, what can we do ?
                    error!(guard.log, "XWayland second fork failed"; "err" => format!("{:?}", e));
                    unsafe { ::nix::libc::exit(1) };
                }
            }
        }
        Err(e) => {
            error!(guard.log, "XWayland first fork failed"; "err" => format!("{:?}", e));
            return Err(());
        }
    };

    let startup_handler = (&mut *guard.source_maker)(inner.clone(), status_me)?;

    guard.instance = Some(XWaylandInstance {
        display_lock: lock,
        wayland_client: client,
        startup_handler: Some(startup_handler),
        wm_fd: Some(x_wm_me),
        started_at: creation_time,
        child_pid: Some(child_pid),
    });

    Ok(())
}

impl<WM: XWindowManager> Inner<WM> {
    // Shutdown the XWayland server and cleanup everything
    fn shutdown(&mut self) {
        // don't do anything if not running
        if let Some(mut instance) = self.instance.take() {
            info!(self.log, "Shutting down XWayland.");
            self.wm.xwayland_exited();
            // kill the client
            instance.wayland_client.kill();
            // remove the event source
            if let Some(s) = instance.startup_handler.take() {
                (self.kill_source)(s);
            }
            // All connections and lockfiles are cleaned by their destructors

            // Remove DISPLAY from the env
            ::std::env::remove_var("DISPLAY");
            // We do like wlroots:
            // > We do not kill the XWayland process, it dies to broken pipe
            // > after we close our side of the wm/wl fds. This is more reliable
            // > than trying to kill something that might no longer be XWayland.
        }
    }
}

fn client_destroy<WM: XWindowManager + 'static, T: Any>(map: &::wayland_server::UserDataMap, data: &mut T) {
    let inner = map.get::<Rc<RefCell<Inner<WM>>>>().unwrap();

    // shutdown the server
    let started_at = inner.borrow().instance.as_ref().map(|i| i.started_at);
    inner.borrow_mut().shutdown();

    // restart it, unless we really just started it, if it crashes right
    // at startup there is no point
    if started_at.map(|t| t.elapsed().as_secs()).unwrap_or(10) > 5 {
        warn!(inner.borrow().log, "XWayland crashed, restarting.");
        let _ = launch(&inner, data);
    } else {
        warn!(
            inner.borrow().log,
            "XWayland crashed less than 5 seconds after its startup, not restarting."
        );
    }
}

fn xwayland_ready<WM: XWindowManager>(inner: &Rc<RefCell<Inner<WM>>>) {
    use nix::sys::wait;
    let mut guard = inner.borrow_mut();
    let inner = &mut *guard;
    // instance should never be None at this point
    let instance = inner.instance.as_mut().unwrap();
    let wm = &mut inner.wm;
    // neither the pid
    let pid = instance.child_pid.unwrap();

    // find out if the launch was a success by waiting on the intermediate child
    let success: bool;
    loop {
        match wait::waitpid(pid, None) {
            Ok(wait::WaitStatus::Exited(_, 0)) => {
                // XWayland was correctly started :)
                success = true;
                break;
            }
            Err(NixError::Sys(Errno::EINTR)) => {
                // interupted, retry
                continue;
            }
            _ => {
                // something went wrong :(
                success = false;
                break;
            }
        }
    }

    if success {
        // signal the WM
        info!(inner.log, "XWayland is ready, signaling the WM.");
        wm.xwayland_ready(
            instance.wm_fd.take().unwrap(), // This is a bug if None
            instance.wayland_client.clone(),
        );

        // setup the environemnt
        ::std::env::set_var("DISPLAY", format!(":{}", instance.display_lock.display()));
    } else {
        error!(
            inner.log,
            "XWayland crashed at startup, will not try to restart it."
        );
    }

    // in all cases, cleanup
    if let Some(s) = instance.startup_handler.take() {
        (inner.kill_source)(s);
    }
}

enum Void {}

/// Exec XWayland with given sockets on given display
///
/// If this returns, that means that something failed
fn exec_xwayland(
    display: u32,
    wayland_socket: UnixStream,
    wm_socket: UnixStream,
    listen_sockets: &[UnixStream],
) -> NixResult<Void> {
    // uset the CLOEXEC flag from the sockets we need to pass
    // to xwayland
    unset_cloexec(&wayland_socket)?;
    unset_cloexec(&wm_socket)?;
    for socket in listen_sockets {
        unset_cloexec(socket)?;
    }
    // prepare the arguments to XWayland
    let mut args = vec![
        CString::new("Xwayland").unwrap(),
        CString::new(format!(":{}", display)).unwrap(),
        CString::new("-rootless").unwrap(),
        CString::new("-terminate").unwrap(),
        CString::new("-wm").unwrap(),
        CString::new(format!("{}", wm_socket.as_raw_fd())).unwrap(),
    ];
    for socket in listen_sockets {
        args.push(CString::new("-listen").unwrap());
        args.push(CString::new(format!("{}", socket.as_raw_fd())).unwrap());
    }
    // setup the environment: clear everything except PATH and XDG_RUNTIME_DIR
    for (key, _) in env::vars_os() {
        if key.to_str() == Some("PATH") || key.to_str() == Some("XDG_RUNTIME_DIR") {
            continue;
        }
        env::remove_var(key);
    }
    // the WAYLAND_SOCKET var tells XWayland where to connect as a wayland client
    env::set_var("WAYLAND_SOCKET", format!("{}", wayland_socket.as_raw_fd()));

    // ignore SIGUSR1, this will make the XWayland server send us this
    // signal when it is ready apparently
    unsafe {
        use nix::sys::signal::*;
        sigaction(
            Signal::SIGUSR1,
            &SigAction::new(SigHandler::SigIgn, SaFlags::empty(), SigSet::empty()),
        )?;
    }

    // run it
    let ret = ::nix::unistd::execvp(
        &CString::new("Xwayland").unwrap(),
        &args.iter().map(AsRef::as_ref).collect::<Vec<_>>(),
    )?;
    // small dance to actually return Void
    match ret {}
}

/// Remove the `O_CLOEXEC` flag from this `Fd`
///
/// This means that the `Fd` will *not* be automatically
/// closed when we `exec()` into XWayland
fn unset_cloexec<F: AsRawFd>(fd: &F) -> NixResult<()> {
    use nix::fcntl::{fcntl, FcntlArg, FdFlag};
    fcntl(fd.as_raw_fd(), FcntlArg::F_SETFD(FdFlag::empty()))?;
    Ok(())
}
<|endoftext|>


<commit_before>use std::{env, fs::read_to_string, path::PathBuf};

use common::{
    dirs,
    eyre::{bail, Result},
    serde_json,
};

use crate::types::ApiToken;

/// The base URL for Stencila Cloud
pub(crate) const BASE_URL: &str = "http://localhost:3000/api/v1"; // "https://stencila.fly.dev/api/v1";

/// Get the path used to store `token.json`, `user.json`, and other files
/// associated with this crate
pub(crate) fn config_dir() -> PathBuf {
    dirs::config_dir()
        .unwrap_or_else(|| env::current_dir().unwrap())
        .join("stencila")
}

/// Get the path of `token.json`
pub(crate) fn token_path() -> PathBuf {
    config_dir().join("token.json")
}

/// Read the current Stencila access token
pub(crate) fn token_read() -> Result<String> {
    let path = token_path();
    if path.exists() {
        let json = read_to_string(token_path())?;
        let token: ApiToken = serde_json::from_str(&json)?;
        Ok(token.token)
    } else {
        bail!("You are not logged in; try doing `stencila login` first");
    }
}

/// Get the path of `user.json`
pub(crate) fn user_path() -> PathBuf {
    config_dir().join("user.json")
}
<commit_msg>chore(Cloud utils): Set `BASE_URL` based on `debug_assertions`<commit_after>use std::{env, fs::read_to_string, path::PathBuf};

use common::{
    dirs,
    eyre::{bail, Result},
    serde_json,
};

use crate::types::ApiToken;

/// The base URL for Stencila Cloud
pub(crate) const BASE_URL: &str = if cfg!(debug_assertions) {
    "http://localhost:3000/api/v1"
} else {
    "https://stencila.fly.dev/api/v1"
};

/// Get the path used to store `token.json`, `user.json`, and other files
/// associated with this crate
pub(crate) fn config_dir() -> PathBuf {
    dirs::config_dir()
        .unwrap_or_else(|| env::current_dir().unwrap())
        .join("stencila")
}

/// Get the path of `token.json`
pub(crate) fn token_path() -> PathBuf {
    config_dir().join("token.json")
}

/// Read the current Stencila access token
pub(crate) fn token_read() -> Result<String> {
    let path = token_path();
    if path.exists() {
        let json = read_to_string(token_path())?;
        let token: ApiToken = serde_json::from_str(&json)?;
        Ok(token.token)
    } else {
        bail!("You are not logged in; try using `stencila login` first");
    }
}

/// Get the path of `user.json`
pub(crate) fn user_path() -> PathBuf {
    config_dir().join("user.json")
}
<|endoftext|>


<commit_before>// rustfmt-normalize_comments: true
// rustfmt-error_on_line_overflow: false

// Imports.

// Long import.
use exceedingly::loooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{
    ItemA, ItemB,
};
use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{
    ItemA, ItemB,
};
use syntax::ast::{ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};

use list::{
    // Another item
    AnotherItem, // Another Comment
    // Last Item
    LastItem,
    // Some item
    SomeItem, /* Comment */
};

use test::{/* A */ self /* B */, Other /* C */};

use syntax;
pub use syntax::ast::{Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath, Expr_};
use Foo::{Bar, Baz};
use {Bar /* comment */, /* Pre-comment! */ Foo};

use std::io;
use std::io;

mod Foo {
    pub use syntax::ast::{
        ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic,
    };

    mod Foo2 {
        pub use syntax::ast::{
            self, ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic,
        };
    }
}

fn test() {
    use Baz::*;
    use Qux;
}

// Simple imports
use bar::quux as kaas;
use foo;
use foo::bar::baz;

// With aliases.
use foo as bar;
use foo::qux as bar;
use foo::{self as bar, baz};
use foo::{baz, qux as bar};

// With absolute paths
use foo;
use foo::Bar;
use foo::{Bar, Baz};
use Foo;
use {Bar, Baz};

// Root globs
use *;
use *;

// spaces used to cause glob imports to disappear (#1356)
use super::*;
use foo::issue_1356::*;

// We shouldn't remove imports which have attributes attached (#1858)
#[cfg(unix)]
use self::unix::{};

// nested imports
use foo::{
    a,
    b,
    bar::{
        baz,
        foo::{a, b, cxxxxxxxxxxxxx, yyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz},
        qux,
        xxxxxxxxxxx,
        yyyyyyyyyyyyy,
        zzzzzzzzzzzzzzzz,
    },
    boo,
    c,
};

use fooo::{
    baar::foobar::{
        xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy,
        zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz,
    },
    bar,
    bar::*,
    x,
    y,
    z,
};

// nested imports with a single sub-tree.
use a::b::c::d;
use a::b::c::*;
use a::b::c::{xxx, yyy, zzz};

// #2645
/// This line is not affected.
// This line is deleted.
use c;
<commit_msg>Fix broken test<commit_after>// rustfmt-normalize_comments: true
// rustfmt-error_on_line_overflow: false

// Imports.

// Long import.
use exceedingly::loooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{
    ItemA, ItemB,
};
use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{
    ItemA, ItemB,
};
use syntax::ast::{ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};

use list::{
    // Another item
    AnotherItem, // Another Comment
    // Last Item
    LastItem,
    // Some item
    SomeItem, // Comment
};

use test::{/* A */ self /* B */, Other /* C */};

use syntax;
pub use syntax::ast::{Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath, Expr_};
use Foo::{Bar, Baz};
use {Bar /* comment */, /* Pre-comment! */ Foo};

use std::io;
use std::io;

mod Foo {
    pub use syntax::ast::{
        ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic,
    };

    mod Foo2 {
        pub use syntax::ast::{
            self, ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic,
        };
    }
}

fn test() {
    use Baz::*;
    use Qux;
}

// Simple imports
use bar::quux as kaas;
use foo;
use foo::bar::baz;

// With aliases.
use foo as bar;
use foo::qux as bar;
use foo::{self as bar, baz};
use foo::{baz, qux as bar};

// With absolute paths
use foo;
use foo::Bar;
use foo::{Bar, Baz};
use Foo;
use {Bar, Baz};

// Root globs
use *;
use *;

// spaces used to cause glob imports to disappear (#1356)
use super::*;
use foo::issue_1356::*;

// We shouldn't remove imports which have attributes attached (#1858)
#[cfg(unix)]
use self::unix::{};

// nested imports
use foo::{
    a,
    b,
    bar::{
        baz,
        foo::{a, b, cxxxxxxxxxxxxx, yyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz},
        qux,
        xxxxxxxxxxx,
        yyyyyyyyyyyyy,
        zzzzzzzzzzzzzzzz,
    },
    boo,
    c,
};

use fooo::{
    baar::foobar::{
        xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy,
        zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz,
    },
    bar,
    bar::*,
    x,
    y,
    z,
};

// nested imports with a single sub-tree.
use a::b::c::d;
use a::b::c::*;
use a::b::c::{xxx, yyy, zzz};

// #2645
/// This line is not affected.
// This line is deleted.
use c;
<|endoftext|>


<commit_before>use core::ops::{Index, IndexMut};

use x86_64::paging::entry::*;
use x86_64::paging::ENTRY_COUNT;

use core::marker::PhantomData;

use ::allocate_frame;

pub const P4: *mut Table<Level4> = 0xffffffff_fffff000 as *mut _;

pub struct Table<L: TableLevel> {
    entries: [Entry; ENTRY_COUNT],
    level: PhantomData<L>,
}

impl<L> Table<L> where L: TableLevel
{
    pub fn is_unused(&self) -> bool {
        if self.entry_count() > 0 {
            return false;
        }

        true
    }

    pub fn zero(&mut self) {
        for entry in self.entries.iter_mut() {
            entry.set_zero();
        }
    }

    /// Set number of entries in first table entry
    fn set_entry_count(&mut self, count: u64) {
        assert!(count <= ENTRY_COUNT as u64, "count can't be greater than ENTRY_COUNT");
        self.entries[0].set_counter_bits(count);
    }

    /// Get number of entries in first table entry
    fn entry_count(&self) -> u64 {
        self.entries[0].counter_bits()
    }

    pub fn increment_entry_count(&mut self) {
        let current_count = self.entry_count();
        self.set_entry_count(current_count + 1);
    }

    pub fn decrement_entry_count(&mut self) {
        let current_count = self.entry_count();
        self.set_entry_count(current_count - 1);
    }

    // pub fn set_entry_count(&mut self, mut count: usize) {
    //     assert!(count <= 512, "count can't be bigger than 512");
    //     let mut count_parts : [usize; 4] = [0; 4];
    //     for count_part in count_parts.iter_mut() {
    //         let part = count & 0x00000000_00000007;
    //         *count_part = part;
    //         count = count >> 3;
    //     }
    //     for i in 0..4 {
    //         self.entries[i].set_counter_bits(count_parts[i]);
    //     }
    // }

    // pub fn entry_count(&self) -> usize {
    //     let mut count_parts : [usize; 4] = [0; 4];
    //     let mut result : usize = 0;
    //     for i in 0..4 {
    //         count_parts[i] = self.entries[i].counter_bits();
    //     }
    //     for count_part in count_parts.iter().rev() {
    //         result = result << 3;
    //         result = result | *count_part;
    //     }
    //     result
    // }

}

impl<L> Table<L> where L: HierarchicalLevel
{
    fn next_table_address(&self, index: usize) -> Option<usize> {
        let entry_flags = self[index].flags();
        if entry_flags.contains(EntryFlags::PRESENT) && !entry_flags.contains(EntryFlags::HUGE_PAGE) {
            let table_address = self as *const _ as usize;
            Some((table_address << 9) | (index << 12))
        } else {
            None
        }
    }

    pub fn next_table(&self, index: usize) -> Option<&Table<L::NextLevel>> {
        self.next_table_address(index)
            .map(|address| unsafe { &*(address as *const _) })
    }

    pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table<L::NextLevel>> {
        self.next_table_address(index)
            .map(|address| unsafe { &mut *(address as *mut _) })
    }

    pub fn next_table_create(&mut self, index: usize) -> &mut Table<L::NextLevel> {
        if self.next_table(index).is_none() {
            assert!(!self.entries[index].flags().contains(EntryFlags::HUGE_PAGE), "mapping code does not support huge pages");
            let frame = allocate_frame().expect("no frames available");
            self.increment_entry_count();
            self.entries[index].set(frame, EntryFlags::PRESENT | EntryFlags::WRITABLE);
            self.next_table_mut(index).unwrap().zero();
        }
        self.next_table_mut(index).unwrap()
    }
}

impl<L> Index<usize> for Table<L> where L: TableLevel {
    type Output = Entry;

    fn index(&self, index: usize) -> &Entry {
        &self.entries[index]
    }
}

impl<L> IndexMut<usize> for Table<L> where L: TableLevel {
    fn index_mut(&mut self, index: usize) -> &mut Entry {
        &mut self.entries[index]
    }
}

pub trait TableLevel {}

pub enum Level4 {}
pub enum Level3 {}
pub enum Level2 {}
pub enum Level1 {}

impl TableLevel for Level4 {}
impl TableLevel for Level3 {}
impl TableLevel for Level2 {}
impl TableLevel for Level1 {}

pub trait HierarchicalLevel: TableLevel {
    type NextLevel: TableLevel;
}

impl HierarchicalLevel for Level4 {
    type NextLevel = Level3;
}
impl HierarchicalLevel for Level3 {
    type NextLevel = Level2;
}
impl HierarchicalLevel for Level2 {
    type NextLevel = Level1;
}
<commit_msg>use debug assert<commit_after>use core::ops::{Index, IndexMut};

use x86_64::paging::entry::*;
use x86_64::paging::ENTRY_COUNT;

use core::marker::PhantomData;

use ::allocate_frame;

pub const P4: *mut Table<Level4> = 0xffffffff_fffff000 as *mut _;

pub struct Table<L: TableLevel> {
    entries: [Entry; ENTRY_COUNT],
    level: PhantomData<L>,
}

impl<L> Table<L> where L: TableLevel
{
    pub fn is_unused(&self) -> bool {
        if self.entry_count() > 0 {
            return false;
        }

        true
    }

    pub fn zero(&mut self) {
        for entry in self.entries.iter_mut() {
            entry.set_zero();
        }
    }

    /// Set number of entries in first table entry
    fn set_entry_count(&mut self, count: u64) {
        debug_assert!(count <= ENTRY_COUNT as u64, "count can't be greater than ENTRY_COUNT");
        self.entries[0].set_counter_bits(count);
    }

    /// Get number of entries in first table entry
    fn entry_count(&self) -> u64 {
        self.entries[0].counter_bits()
    }

    pub fn increment_entry_count(&mut self) {
        let current_count = self.entry_count();
        self.set_entry_count(current_count + 1);
    }

    pub fn decrement_entry_count(&mut self) {
        let current_count = self.entry_count();
        self.set_entry_count(current_count - 1);
    }

    // pub fn set_entry_count(&mut self, mut count: usize) {
    //     assert!(count <= 512, "count can't be bigger than 512");
    //     let mut count_parts : [usize; 4] = [0; 4];
    //     for count_part in count_parts.iter_mut() {
    //         let part = count & 0x00000000_00000007;
    //         *count_part = part;
    //         count = count >> 3;
    //     }
    //     for i in 0..4 {
    //         self.entries[i].set_counter_bits(count_parts[i]);
    //     }
    // }

    // pub fn entry_count(&self) -> usize {
    //     let mut count_parts : [usize; 4] = [0; 4];
    //     let mut result : usize = 0;
    //     for i in 0..4 {
    //         count_parts[i] = self.entries[i].counter_bits();
    //     }
    //     for count_part in count_parts.iter().rev() {
    //         result = result << 3;
    //         result = result | *count_part;
    //     }
    //     result
    // }

}

impl<L> Table<L> where L: HierarchicalLevel
{
    fn next_table_address(&self, index: usize) -> Option<usize> {
        let entry_flags = self[index].flags();
        if entry_flags.contains(EntryFlags::PRESENT) && !entry_flags.contains(EntryFlags::HUGE_PAGE) {
            let table_address = self as *const _ as usize;
            Some((table_address << 9) | (index << 12))
        } else {
            None
        }
    }

    pub fn next_table(&self, index: usize) -> Option<&Table<L::NextLevel>> {
        self.next_table_address(index)
            .map(|address| unsafe { &*(address as *const _) })
    }

    pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table<L::NextLevel>> {
        self.next_table_address(index)
            .map(|address| unsafe { &mut *(address as *mut _) })
    }

    pub fn next_table_create(&mut self, index: usize) -> &mut Table<L::NextLevel> {
        if self.next_table(index).is_none() {
            assert!(!self.entries[index].flags().contains(EntryFlags::HUGE_PAGE), "mapping code does not support huge pages");
            let frame = allocate_frame().expect("no frames available");
            self.increment_entry_count();
            self.entries[index].set(frame, EntryFlags::PRESENT | EntryFlags::WRITABLE);
            self.next_table_mut(index).unwrap().zero();
        }
        self.next_table_mut(index).unwrap()
    }
}

impl<L> Index<usize> for Table<L> where L: TableLevel {
    type Output = Entry;

    fn index(&self, index: usize) -> &Entry {
        &self.entries[index]
    }
}

impl<L> IndexMut<usize> for Table<L> where L: TableLevel {
    fn index_mut(&mut self, index: usize) -> &mut Entry {
        &mut self.entries[index]
    }
}

pub trait TableLevel {}

pub enum Level4 {}
pub enum Level3 {}
pub enum Level2 {}
pub enum Level1 {}

impl TableLevel for Level4 {}
impl TableLevel for Level3 {}
impl TableLevel for Level2 {}
impl TableLevel for Level1 {}

pub trait HierarchicalLevel: TableLevel {
    type NextLevel: TableLevel;
}

impl HierarchicalLevel for Level4 {
    type NextLevel = Level3;
}
impl HierarchicalLevel for Level3 {
    type NextLevel = Level2;
}
impl HierarchicalLevel for Level2 {
    type NextLevel = Level1;
}
<|endoftext|>


<commit_before>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std;

use bindings;
use error::{Error, Result};
use libusb_device::LibUsbDevice;
use std::sync::Arc;

pub struct LibUsbContextInner {
    context: *mut bindings::libusb_context,
}

// Safe because libusb_context could be accessed from multiple threads safely.
unsafe impl Send for LibUsbContextInner {}
unsafe impl Sync for LibUsbContextInner {}

impl Drop for LibUsbContextInner {
    fn drop(&mut self) {
        // Safe beacuse 'self.context' points to a valid context allocated by libusb_init.
        unsafe {
            bindings::libusb_exit(self.context);
        }
    }
}

/// Wrapper for libusb_context. The libusb libary initialization/deinitialization
/// is managed by this context.
/// See: http://libusb.sourceforge.net/api-1.0/group__libusb__lib.html
#[derive(Clone)]
pub struct LibUsbContext {
    inner: Arc<LibUsbContextInner>,
}

impl LibUsbContext {
    /// Create a new LibUsbContext.
    pub fn new() -> Result<LibUsbContext> {
        let mut ctx: *mut bindings::libusb_context = std::ptr::null_mut();
        // Safe because '&mut ctx' points to a valid memory (on stack).
        try_libusb!(unsafe { bindings::libusb_init(&mut ctx) });
        Ok(LibUsbContext {
            inner: Arc::new(LibUsbContextInner { context: ctx }),
        })
    }

    /// Returns a list of USB devices currently attached to the system.
    pub fn get_device_iter(&self) -> Result<DeviceIter> {
        let mut list: *mut *mut bindings::libusb_device = std::ptr::null_mut();
        // Safe because 'inner.context' points to a valid context and '&mut list' points to a valid
        // memory.
        try_libusb!(unsafe { bindings::libusb_get_device_list(self.inner.context, &mut list) });

        Ok(DeviceIter {
            context: self.inner.clone(),
            list,
            index: 0,
        })
    }

    /// Check at runtime if the loaded library has a given capability.
    pub fn has_capability(&self, cap: u32) -> bool {
        // Safe because libusb_init is called before this call happens.
        unsafe { bindings::libusb_has_capability(cap) != 0 }
    }

    /// Return an iter of poll fds. Those fds that should be polled to handle libusb events.
    pub fn get_pollfd_iter(&self) -> PollFdIter {
        // Safe because 'inner.context' is inited.
        let list: *mut *const bindings::libusb_pollfd =
            unsafe { bindings::libusb_get_pollfds(self.inner.context) };
        PollFdIter { list, index: 0 }
    }

    /// Handle libusb events in a non block way.
    pub fn handle_event_nonblock(&self) {
        static mut zero_time: bindings::timeval = bindings::timeval {
            tv_sec: 0,
            tv_usec: 0,
        };
        // Safe because 'inner.context' points to valid context.
        unsafe {
            bindings::libusb_handle_events_timeout_completed(
                self.inner.context,
                &mut zero_time as *mut bindings::timeval,
                std::ptr::null_mut(),
            );
        }
    }
}

/// Iterator for device list.
pub struct DeviceIter {
    context: Arc<LibUsbContextInner>,
    list: *mut *mut bindings::libusb_device,
    index: isize,
}

impl Drop for DeviceIter {
    fn drop(&mut self) {
        // Safe because 'self.list' is inited by a valid pointer from libusb_get_device_list.
        unsafe {
            bindings::libusb_free_device_list(self.list, 1);
        }
    }
}

impl Iterator for DeviceIter {
    type Item = LibUsbDevice;

    fn next(&mut self) -> Option<LibUsbDevice> {
        // Safe becuase 'self.list' is valid, the list is null terminated.
        unsafe {
            let current_ptr = self.list.offset(self.index);
            if (*current_ptr).is_null() {
                return None;
            }
            self.index += 1;
            Some(LibUsbDevice::new(self.context.clone(), *current_ptr))
        }
    }
}

/// Iterator for pollfds.
pub struct PollFdIter {
    list: *mut *const bindings::libusb_pollfd,
    index: isize,
}

impl Drop for PollFdIter {
    fn drop(&mut self) {
        // Safe because 'self.list' points to valid memory of pollfd list.
        unsafe {
            bindings::libusb_free_pollfds(self.list);
        }
    }
}

impl Iterator for PollFdIter {
    type Item = bindings::libusb_pollfd;

    fn next(&mut self) -> Option<bindings::libusb_pollfd> {
        // Safe because 'self.index' never grow out of the null pointer index.
        unsafe {
            let current_ptr = self.list.offset(self.index);
            if (*current_ptr).is_null() {
                return None;
            }

            self.index += 1;
            // Safe because 'current_ptr' is not null.
            Some((**current_ptr).clone())
        }
    }
}
<commit_msg>usb_util: Add pollfd change handler.<commit_after>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std;
use std::os::raw::{c_short, c_void};
use std::os::unix::io::RawFd;

use bindings;
use error::{Error, Result};
use libusb_device::LibUsbDevice;
use std::sync::{Arc, Mutex};

pub struct LibUsbContextInner {
    context: *mut bindings::libusb_context,
    pollfd_change_handler: Mutex<Option<Box<PollfdChangeHandlerHolder>>>,
}

// Safe because libusb_context could be accessed from multiple threads safely.
unsafe impl Send for LibUsbContextInner {}
unsafe impl Sync for LibUsbContextInner {}

impl LibUsbContextInner {
    /// Remove the previous registered notifiers.
    pub fn remove_pollfd_notifiers(&self) {
        // Safe because 'self.context' is valid.
        unsafe {
            bindings::libusb_set_pollfd_notifiers(self.context, None, None, std::ptr::null_mut());
        }
    }
}

impl Drop for LibUsbContextInner {
    fn drop(&mut self) {
        // Avoid pollfd change handler call when libusb_exit is called.
        self.remove_pollfd_notifiers();
        // Safe beacuse 'self.context' points to a valid context allocated by libusb_init.
        unsafe {
            bindings::libusb_exit(self.context);
        }
    }
}

/// Wrapper for libusb_context. The libusb libary initialization/deinitialization
/// is managed by this context.
/// See: http://libusb.sourceforge.net/api-1.0/group__libusb__lib.html
#[derive(Clone)]
pub struct LibUsbContext {
    inner: Arc<LibUsbContextInner>,
}

impl LibUsbContext {
    /// Create a new LibUsbContext.
    pub fn new() -> Result<LibUsbContext> {
        let mut ctx: *mut bindings::libusb_context = std::ptr::null_mut();
        // Safe because '&mut ctx' points to a valid memory (on stack).
        try_libusb!(unsafe { bindings::libusb_init(&mut ctx) });
        Ok(LibUsbContext {
            inner: Arc::new(LibUsbContextInner {
                context: ctx,
                pollfd_change_handler: Mutex::new(None),
            }),
        })
    }

    /// Returns a list of USB devices currently attached to the system.
    pub fn get_device_iter(&self) -> Result<DeviceIter> {
        let mut list: *mut *mut bindings::libusb_device = std::ptr::null_mut();
        // Safe because 'inner.context' points to a valid context and '&mut list' points to a valid
        // memory.
        try_libusb!(unsafe { bindings::libusb_get_device_list(self.inner.context, &mut list) });

        Ok(DeviceIter {
            context: self.inner.clone(),
            list,
            index: 0,
        })
    }

    /// Check at runtime if the loaded library has a given capability.
    pub fn has_capability(&self, cap: u32) -> bool {
        // Safe because libusb_init is called before this call happens.
        unsafe { bindings::libusb_has_capability(cap) != 0 }
    }

    /// Return an iter of poll fds. Those fds that should be polled to handle libusb events.
    pub fn get_pollfd_iter(&self) -> PollFdIter {
        // Safe because 'inner.context' is inited.
        let list: *mut *const bindings::libusb_pollfd =
            unsafe { bindings::libusb_get_pollfds(self.inner.context) };
        PollFdIter { list, index: 0 }
    }

    /// Handle libusb events in a non block way.
    pub fn handle_events_nonblock(&self) {
        static mut zero_time: bindings::timeval = bindings::timeval {
            tv_sec: 0,
            tv_usec: 0,
        };
        // Safe because 'inner.context' points to valid context.
        unsafe {
            bindings::libusb_handle_events_timeout_completed(
                self.inner.context,
                &mut zero_time as *mut bindings::timeval,
                std::ptr::null_mut(),
            );
        }
    }

    /// Set a handler that could handle pollfd change events.
    pub fn set_pollfd_notifiers(&self, handler: Box<LibUsbPollfdChangeHandler>) {
        // LibUsbContext is alive when any libusb related function is called. It owns the handler,
        // thus the handler memory is always valid when callback is invoked.
        let holder = Box::new(PollfdChangeHandlerHolder { handler });
        let raw_holder = Box::into_raw(holder);
        unsafe {
            bindings::libusb_set_pollfd_notifiers(
                self.inner.context,
                Some(pollfd_added_cb),
                Some(pollfd_removed_cb),
                raw_holder as *mut c_void,
            );
        }
        // Safe because raw_holder is from Boxed pointer.
        let holder = unsafe { Box::from_raw(raw_holder) };
        *self.inner.pollfd_change_handler.lock().unwrap() = Some(holder);
    }

    /// Remove the previous registered notifiers.
    pub fn remove_pollfd_notifiers(&self) {
        self.inner.remove_pollfd_notifiers();
    }
}

/// Iterator for device list.
pub struct DeviceIter {
    context: Arc<LibUsbContextInner>,
    list: *mut *mut bindings::libusb_device,
    index: isize,
}

impl Drop for DeviceIter {
    fn drop(&mut self) {
        // Safe because 'self.list' is inited by a valid pointer from libusb_get_device_list.
        unsafe {
            bindings::libusb_free_device_list(self.list, 1);
        }
    }
}

impl Iterator for DeviceIter {
    type Item = LibUsbDevice;

    fn next(&mut self) -> Option<LibUsbDevice> {
        // Safe becuase 'self.list' is valid, the list is null terminated.
        unsafe {
            let current_ptr = self.list.offset(self.index);
            if (*current_ptr).is_null() {
                return None;
            }
            self.index += 1;
            Some(LibUsbDevice::new(self.context.clone(), *current_ptr))
        }
    }
}

/// Iterator for pollfds.
pub struct PollFdIter {
    list: *mut *const bindings::libusb_pollfd,
    index: isize,
}

impl Drop for PollFdIter {
    fn drop(&mut self) {
        // Safe because 'self.list' points to valid memory of pollfd list.
        unsafe {
            bindings::libusb_free_pollfds(self.list);
        }
    }
}

impl Iterator for PollFdIter {
    type Item = bindings::libusb_pollfd;

    fn next(&mut self) -> Option<bindings::libusb_pollfd> {
        // Safe because 'self.index' never grow out of the null pointer index.
        unsafe {
            let current_ptr = self.list.offset(self.index);
            if (*current_ptr).is_null() {
                return None;
            }

            self.index += 1;
            // Safe because 'current_ptr' is not null.
            Some((**current_ptr).clone())
        }
    }
}

/// Trait for handler that handles Pollfd Change events.
pub trait LibUsbPollfdChangeHandler: Send + Sync + 'static {
    fn add_poll_fd(&self, fd: RawFd, events: c_short);
    fn remove_poll_fd(&self, fd: RawFd);
}

// This struct owns LibUsbPollfdChangeHandler. We need it because it's not possible to cast void
// pointer to trait pointer.
struct PollfdChangeHandlerHolder {
    handler: Box<LibUsbPollfdChangeHandler>,
}

// This function is safe when user_data points to valid PollfdChangeHandlerHolder.
unsafe extern "C" fn pollfd_added_cb(fd: RawFd, events: c_short, user_data: *mut c_void) {
    // Safe because user_data was casted from holder.
    let keeper = &*(user_data as *mut PollfdChangeHandlerHolder);
    keeper.handler.add_poll_fd(fd, events);
}

// This function is safe when user_data points to valid PollfdChangeHandlerHolder.
unsafe extern "C" fn pollfd_removed_cb(fd: RawFd, user_data: *mut c_void) {
    // Safe because user_data was casted from holder.
    let keeper = &*(user_data as *mut PollfdChangeHandlerHolder);
    keeper.handler.remove_poll_fd(fd);
}
<|endoftext|>


<commit_before>#![crate_name = "orbtk"]
#![crate_type = "lib"]

//! # OrbTK - The Orbital Toolkit
//!
//! ![Welcome to the OrbTk planet.][orbtk_planet]
//!
//! The `OrbTK` crate implements a cross-platform (G)UI toolkit for
//! building scalable user interfaces. The codebase is natively build
//! with the `Rust` programming language.
//!
//! `OrbTK` provides a [functional reactive-like][functional_reative] API. It depends on
//! the rust [`DCES`][dces] crate, that provides an Entity Component
//! System. Interaction with `DCES` is managed via the `Entity
//! Component Manager`(ECM), a wrapper API, that transparently mapps `OrbTK` widgets
//! to `ECM`  entities and `OrbTK` properties to `ECM` components.
//!
//! The main goals of `OrbTk` are speed, ease of use, and cross-platform compatibility.
//!
//! Happy 🦀 hacking! ✨
//!
//! [dces]: https://docs.rs/dces
//! [functional_reative]: https://en.wikipedia.org/wiki/Functional_reactive_programming
//! [orbtk_planet]: https://raw.githubusercontent.com/rzerres/orbtk/wip_documentation/orbtk/images/orbtk_planet.svg
// //! [orbtk_planet]: https://raw.githubusercontent.com/redox-os/orbtk/develop/orbtk/images/orbtk_planet.svg

//#![feature(extern_doc)]
//#[doc(include="../README.md")]

pub use orbtk_orbclient::prelude::initialize;

pub mod core {
    pub use orbtk_core::application;
    pub use orbtk_core::localization;
    pub use orbtk_core::macros;
    pub use orbtk_core::prelude::*;
    pub use orbtk_core::theming;
    pub use orbtk_core::tree;
}

pub mod proc_macros {
    pub use orbtk_proc_macros::*;
}

pub mod render {
    pub use orbtk_tinyskia::*;
}

pub mod shell {
    pub use orbtk_orbclient::prelude::*;
}

pub mod utils {
    pub use orbtk_utils::*;
}

pub mod widgets {
    pub use orbtk_widgets::*;
}

pub mod prelude;

mod application;

pub use self::application::*;
<commit_msg>orbtk: update lib documentation<commit_after>#![crate_name = "orbtk"]
#![crate_type = "lib"]

//! # OrbTK - The Orbital Toolkit
//!
//! ![Welcome to the OrbTk planet.][orbtk_planet]
//!
//! The `OrbTK` crate implements a cross-platform (G)UI toolkit for
//! building scalable user interfaces. The codebase is natively build
//! with the `Rust` programming language.
//!
//! `OrbTK` provides a [functional reactive-like][functional_reative] API. It depends on
//! the rust [`DCES`][dces] crate, that provides an Entity Component
//! System. Interaction with `DCES` is managed via the `Entity
//! Component Manager`(ECM), a wrapper API, that transparently mapps `OrbTK` widgets
//! to `ECM`  entities and `OrbTK` properties to `ECM` components.
//!
//! The main goals of `OrbTk` are speed, ease of use, and cross-platform compatibility.
//!
//! Happy 🦀 hacking! ✨
//!
//! [dces]: https://docs.rs/dces
//! [functional_reative]: https://en.wikipedia.org/wiki/Functional_reactive_programming
//! [orbtk_planet]: https://raw.githubusercontent.com/rzerres/orbtk/wip_documentation/orbtk/images/orbtk_planet.svg
// //! [orbtk_planet]: https://raw.githubusercontent.com/redox-os/orbtk/develop/orbtk/images/orbtk_planet.svg

//#![feature(extern_doc)]
//#[doc(include="../README.md")]

/// Tries to make your OrbTK experience more convenient.
/// It will automatically import traits and types into scope, that you likely need in your app.
pub use orbtk_orbclient::prelude::initialize;

/// Handles core implenentations (OrbTK building blocks).
pub mod core {
    pub use orbtk_core::application;
    pub use orbtk_core::localization;
    pub use orbtk_core::macros;
    pub use orbtk_core::prelude::*;
    pub use orbtk_core::theming;
    pub use orbtk_core::tree;
}

/// Handles procedural macros.
pub mod proc_macros {
    pub use orbtk_proc_macros::*;
}

/// Handles renderer implementations.
pub mod render {
    pub use orbtk_tinyskia::*;
}

/// Handles shell interaction implementations.
pub mod shell {
    pub use orbtk_orbclient::prelude::*;
}

/// Handles helper utilities and global methods.
pub mod utils {
    pub use orbtk_utils::*;
}

/// Handle widget implementations.
pub mod widgets {
    pub use orbtk_widgets::*;
}

/// Pre-selects commonly used OrbTk crates and put them into scope.
pub mod prelude;

mod application;

pub use self::application::*;
<|endoftext|>


<commit_before>// Copyright 2017 Rich Lane <lanerl@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0> or
// the MIT license <http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! This module parses eBPF assembly language source code.

use combine::char::{alpha_num, char, digit, hex_digit, spaces, string};
use combine::{between, eof, many, many1, one_of, optional, Parser, ParseError, ParseResult, parser,
              sep_by, try, State, Stream};
use combine::primitives::{Error, Info};

/// Operand of an instruction.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Operand {
    /// Register number.
    Register(i64),
    /// Jump offset or immediate.
    Integer(i64),
    /// Register number and offset.
    Memory(i64, i64),
    /// Used for pattern matching.
    Nil,
}

/// Parsed instruction.
#[derive(Debug, PartialEq)]
pub struct Instruction {
    /// Instruction name.
    pub name: String,
    /// Operands.
    pub operands: Vec<Operand>,
}

fn ident<I>(input: I) -> ParseResult<String, I>
    where I: Stream<Item = char>
{
    many1(alpha_num()).parse_stream(input)
}

fn integer<I>(input: I) -> ParseResult<i64, I>
    where I: Stream<Item = char>
{
    let sign = optional(one_of("-+".chars())).map(|x| match x {
        Some('-') => -1,
        _ => 1,
    });
    let hex = string("0x")
        .with(many1(hex_digit()))
        .map(|x: String| u64::from_str_radix(&x, 16).unwrap() as i64);
    let dec = many1(digit()).map(|x: String| i64::from_str_radix(&x, 10).unwrap());
    (sign, try(hex).or(dec)).map(|(s, x)| s * x).parse_stream(input)
}

fn register<I>(input: I) -> ParseResult<i64, I>
    where I: Stream<Item = char>
{
    char('r')
        .with(many1(digit()))
        .map(|x: String| i64::from_str_radix(&x, 10).unwrap())
        .parse_stream(input)
}

fn operand<I>(input: I) -> ParseResult<Operand, I>
    where I: Stream<Item = char>
{
    let register_operand = parser(register).map(Operand::Register);
    let immediate = parser(integer).map(Operand::Integer);
    let memory = between(char('['),
                         char(']'),
                         (parser(register), optional(parser(integer))))
        .map(|t| Operand::Memory(t.0, t.1.unwrap_or(0)));
    register_operand.or(immediate).or(memory).parse_stream(input)
}

fn instruction<I>(input: I) -> ParseResult<Instruction, I>
    where I: Stream<Item = char>
{
    let operands = sep_by(parser(operand), char(',').skip(spaces()));
    (parser(ident).skip(spaces()), operands, spaces())
        .map(|t| {
            Instruction {
                name: t.0,
                operands: t.1,
            }
        })
        .parse_stream(input)
}

fn format_info(info: &Info<char, &str>) -> String {
    match *info {
        Info::Token(x) => format!("{:?}", x),
        Info::Range(x) => format!("{:?}", x),
        Info::Owned(ref x) => x.clone(),
        Info::Borrowed(x) => x.to_string(),
    }
}

fn format_error(error: &Error<char, &str>) -> String {
    match *error {
        Error::Unexpected(ref x) => format!("unexpected {}", format_info(x)),
        Error::Expected(ref x) => format!("expected {}", format_info(x)),
        Error::Message(ref x) => format_info(x),
        Error::Other(ref x) => format!("{:?}", x),
    }
}

fn format_parse_error(parse_error: ParseError<State<&str>>) -> String {
    format!("Parse error at line {} column {}: {}",
            parse_error.position.line,
            parse_error.position.column,
            parse_error.errors.iter().map(format_error).collect::<Vec<String>>().join(", "))
}

/// Parse a string into a list of instructions.
///
/// The instructions are not validated and may have invalid names and operand types.
pub fn parse(input: &str) -> Result<Vec<Instruction>, String> {
    match spaces().with(many(parser(instruction)).skip(eof())).parse(State::new(input)) {
        Ok((insts, _)) => Ok(insts),
        Err(err) => Err(format_parse_error(err)),
    }
}

#[cfg(test)]
mod tests {
    use combine::{Parser, parser};
    use super::{ident, integer, register, operand, instruction, Operand, Instruction};

    #[test]
    fn test_ident() {
        assert_eq!(parser(ident).parse("nop"), Ok(("nop".to_string(), "")));
        assert_eq!(parser(ident).parse("add32"), Ok(("add32".to_string(), "")));
        assert_eq!(parser(ident).parse("add32*"),
                   Ok(("add32".to_string(), "*")));
    }

    #[test]
    fn test_integer() {
        assert_eq!(parser(integer).parse("0"), Ok((0, "")));
        assert_eq!(parser(integer).parse("42"), Ok((42, "")));
        assert_eq!(parser(integer).parse("+42"), Ok((42, "")));
        assert_eq!(parser(integer).parse("-42"), Ok((-42, "")));
        assert_eq!(parser(integer).parse("0x0"), Ok((0, "")));
        assert_eq!(parser(integer).parse("0x123456789abcdef0"),
                   Ok((0x123456789abcdef0, "")));
        assert_eq!(parser(integer).parse("-0x1f"), Ok((-31, "")));
    }

    #[test]
    fn test_register() {
        assert_eq!(parser(register).parse("r0"), Ok((0, "")));
        assert_eq!(parser(register).parse("r15"), Ok((15, "")));
    }

    #[test]
    fn test_operand() {
        assert_eq!(parser(operand).parse("r0"), Ok((Operand::Register(0), "")));
        assert_eq!(parser(operand).parse("r15"),
                   Ok((Operand::Register(15), "")));
        assert_eq!(parser(operand).parse("0"), Ok((Operand::Integer(0), "")));
        assert_eq!(parser(operand).parse("42"), Ok((Operand::Integer(42), "")));
        assert_eq!(parser(operand).parse("[r1]"),
                   Ok((Operand::Memory(1, 0), "")));
        assert_eq!(parser(operand).parse("[r3+5]"),
                   Ok((Operand::Memory(3, 5), "")));
        assert_eq!(parser(operand).parse("[r3+0x1f]"),
                   Ok((Operand::Memory(3, 31), "")));
        assert_eq!(parser(operand).parse("[r3-0x1f]"),
                   Ok((Operand::Memory(3, -31), "")));
    }

    #[test]
    fn test_instruction() {
        assert_eq!(parser(instruction).parse("exit"),
                   Ok((Instruction {
                           name: "exit".to_string(),
                           operands: vec![],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("call 2"),
                   Ok((Instruction {
                           name: "call".to_string(),
                           operands: vec![Operand::Integer(2)],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("addi r1, 2"),
                   Ok((Instruction {
                           name: "addi".to_string(),
                           operands: vec![Operand::Register(1), Operand::Integer(2)],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("ldxb r2, [r1+12]"),
                   Ok((Instruction {
                           name: "ldxb".to_string(),
                           operands: vec![Operand::Register(2), Operand::Memory(1, 12)],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("lsh r3, 0x8"),
                   Ok((Instruction {
                           name: "lsh".to_string(),
                           operands: vec![Operand::Register(3), Operand::Integer(8)],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("jne r3, 0x8, +37"),
                   Ok((Instruction {
                           name: "jne".to_string(),
                           operands: vec![Operand::Register(3),
                                          Operand::Integer(8),
                                          Operand::Integer(37)],
                       },
                       "")));

        // Whitespace between operands is optional.
        assert_eq!(parser(instruction).parse("jne r3,0x8,+37"),
                   Ok((Instruction {
                           name: "jne".to_string(),
                           operands: vec![Operand::Register(3),
                                          Operand::Integer(8),
                                          Operand::Integer(37)],
                       },
                       "")));
    }

}
<commit_msg>src/asm_parser.rs: add example to parse() function documentation<commit_after>// Copyright 2017 Rich Lane <lanerl@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0> or
// the MIT license <http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! This module parses eBPF assembly language source code.

use combine::char::{alpha_num, char, digit, hex_digit, spaces, string};
use combine::{between, eof, many, many1, one_of, optional, Parser, ParseError, ParseResult, parser,
              sep_by, try, State, Stream};
use combine::primitives::{Error, Info};

/// Operand of an instruction.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Operand {
    /// Register number.
    Register(i64),
    /// Jump offset or immediate.
    Integer(i64),
    /// Register number and offset.
    Memory(i64, i64),
    /// Used for pattern matching.
    Nil,
}

/// Parsed instruction.
#[derive(Debug, PartialEq)]
pub struct Instruction {
    /// Instruction name.
    pub name: String,
    /// Operands.
    pub operands: Vec<Operand>,
}

fn ident<I>(input: I) -> ParseResult<String, I>
    where I: Stream<Item = char>
{
    many1(alpha_num()).parse_stream(input)
}

fn integer<I>(input: I) -> ParseResult<i64, I>
    where I: Stream<Item = char>
{
    let sign = optional(one_of("-+".chars())).map(|x| match x {
        Some('-') => -1,
        _ => 1,
    });
    let hex = string("0x")
        .with(many1(hex_digit()))
        .map(|x: String| u64::from_str_radix(&x, 16).unwrap() as i64);
    let dec = many1(digit()).map(|x: String| i64::from_str_radix(&x, 10).unwrap());
    (sign, try(hex).or(dec)).map(|(s, x)| s * x).parse_stream(input)
}

fn register<I>(input: I) -> ParseResult<i64, I>
    where I: Stream<Item = char>
{
    char('r')
        .with(many1(digit()))
        .map(|x: String| i64::from_str_radix(&x, 10).unwrap())
        .parse_stream(input)
}

fn operand<I>(input: I) -> ParseResult<Operand, I>
    where I: Stream<Item = char>
{
    let register_operand = parser(register).map(Operand::Register);
    let immediate = parser(integer).map(Operand::Integer);
    let memory = between(char('['),
                         char(']'),
                         (parser(register), optional(parser(integer))))
        .map(|t| Operand::Memory(t.0, t.1.unwrap_or(0)));
    register_operand.or(immediate).or(memory).parse_stream(input)
}

fn instruction<I>(input: I) -> ParseResult<Instruction, I>
    where I: Stream<Item = char>
{
    let operands = sep_by(parser(operand), char(',').skip(spaces()));
    (parser(ident).skip(spaces()), operands, spaces())
        .map(|t| {
            Instruction {
                name: t.0,
                operands: t.1,
            }
        })
        .parse_stream(input)
}

fn format_info(info: &Info<char, &str>) -> String {
    match *info {
        Info::Token(x) => format!("{:?}", x),
        Info::Range(x) => format!("{:?}", x),
        Info::Owned(ref x) => x.clone(),
        Info::Borrowed(x) => x.to_string(),
    }
}

fn format_error(error: &Error<char, &str>) -> String {
    match *error {
        Error::Unexpected(ref x) => format!("unexpected {}", format_info(x)),
        Error::Expected(ref x) => format!("expected {}", format_info(x)),
        Error::Message(ref x) => format_info(x),
        Error::Other(ref x) => format!("{:?}", x),
    }
}

fn format_parse_error(parse_error: ParseError<State<&str>>) -> String {
    format!("Parse error at line {} column {}: {}",
            parse_error.position.line,
            parse_error.position.column,
            parse_error.errors.iter().map(format_error).collect::<Vec<String>>().join(", "))
}

/// Parse a string into a list of instructions.
///
/// The instructions are not validated and may have invalid names and operand types.
///
/// # Examples
///
/// ```
/// use rbpf::asm_parser;
///
/// // Taken from test_ldxh unit test.
/// let insn_str1 = "ldxh r4, [r1+12]";
/// assert_eq!(asm_parser::parse(insn_str1),
///            Ok(vec![asm_parser::Instruction {
///                        name: "ldxh".to_string(),
///                        operands: vec![asm_parser::Operand::Register(4),
///                                       asm_parser::Operand::Memory(1, 12)
///                                       ],
///                    }]));
///
/// // Taken from test_error_eof unit test: unexpected end of input in a register name.
/// let insn_str2 = "lsh r";
/// assert_eq!(asm_parser::parse(insn_str2),
///            Err("Parse error at line 1 column 6: unexpected end of input, expected digit"
///                .to_string()));
/// ```
pub fn parse(input: &str) -> Result<Vec<Instruction>, String> {
    match spaces().with(many(parser(instruction)).skip(eof())).parse(State::new(input)) {
        Ok((insts, _)) => Ok(insts),
        Err(err) => Err(format_parse_error(err)),
    }
}

#[cfg(test)]
mod tests {
    use combine::{Parser, parser};
    use super::{ident, integer, register, operand, instruction, Operand, Instruction};

    #[test]
    fn test_ident() {
        assert_eq!(parser(ident).parse("nop"), Ok(("nop".to_string(), "")));
        assert_eq!(parser(ident).parse("add32"), Ok(("add32".to_string(), "")));
        assert_eq!(parser(ident).parse("add32*"),
                   Ok(("add32".to_string(), "*")));
    }

    #[test]
    fn test_integer() {
        assert_eq!(parser(integer).parse("0"), Ok((0, "")));
        assert_eq!(parser(integer).parse("42"), Ok((42, "")));
        assert_eq!(parser(integer).parse("+42"), Ok((42, "")));
        assert_eq!(parser(integer).parse("-42"), Ok((-42, "")));
        assert_eq!(parser(integer).parse("0x0"), Ok((0, "")));
        assert_eq!(parser(integer).parse("0x123456789abcdef0"),
                   Ok((0x123456789abcdef0, "")));
        assert_eq!(parser(integer).parse("-0x1f"), Ok((-31, "")));
    }

    #[test]
    fn test_register() {
        assert_eq!(parser(register).parse("r0"), Ok((0, "")));
        assert_eq!(parser(register).parse("r15"), Ok((15, "")));
    }

    #[test]
    fn test_operand() {
        assert_eq!(parser(operand).parse("r0"), Ok((Operand::Register(0), "")));
        assert_eq!(parser(operand).parse("r15"),
                   Ok((Operand::Register(15), "")));
        assert_eq!(parser(operand).parse("0"), Ok((Operand::Integer(0), "")));
        assert_eq!(parser(operand).parse("42"), Ok((Operand::Integer(42), "")));
        assert_eq!(parser(operand).parse("[r1]"),
                   Ok((Operand::Memory(1, 0), "")));
        assert_eq!(parser(operand).parse("[r3+5]"),
                   Ok((Operand::Memory(3, 5), "")));
        assert_eq!(parser(operand).parse("[r3+0x1f]"),
                   Ok((Operand::Memory(3, 31), "")));
        assert_eq!(parser(operand).parse("[r3-0x1f]"),
                   Ok((Operand::Memory(3, -31), "")));
    }

    #[test]
    fn test_instruction() {
        assert_eq!(parser(instruction).parse("exit"),
                   Ok((Instruction {
                           name: "exit".to_string(),
                           operands: vec![],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("call 2"),
                   Ok((Instruction {
                           name: "call".to_string(),
                           operands: vec![Operand::Integer(2)],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("addi r1, 2"),
                   Ok((Instruction {
                           name: "addi".to_string(),
                           operands: vec![Operand::Register(1), Operand::Integer(2)],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("ldxb r2, [r1+12]"),
                   Ok((Instruction {
                           name: "ldxb".to_string(),
                           operands: vec![Operand::Register(2), Operand::Memory(1, 12)],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("lsh r3, 0x8"),
                   Ok((Instruction {
                           name: "lsh".to_string(),
                           operands: vec![Operand::Register(3), Operand::Integer(8)],
                       },
                       "")));

        assert_eq!(parser(instruction).parse("jne r3, 0x8, +37"),
                   Ok((Instruction {
                           name: "jne".to_string(),
                           operands: vec![Operand::Register(3),
                                          Operand::Integer(8),
                                          Operand::Integer(37)],
                       },
                       "")));

        // Whitespace between operands is optional.
        assert_eq!(parser(instruction).parse("jne r3,0x8,+37"),
                   Ok((Instruction {
                           name: "jne".to_string(),
                           operands: vec![Operand::Register(3),
                                          Operand::Integer(8),
                                          Operand::Integer(37)],
                       },
                       "")));
    }

}
<|endoftext|>


<commit_before>use chrono::prelude::*;
use clap::{App, SubCommand, Arg, ArgMatches};
use futures::prelude::*;
use globset::{Glob, GlobSetBuilder};

use attaca::Repository;
use attaca::repository::Head;

use errors::*;
use trace::Progress;

pub fn command() -> App<'static, 'static> {
    SubCommand::with_name("commit")
        .help("Commit a change to the local repository.")
        .arg(
            Arg::with_name("INCLUDE")
                .short("i")
                .long("inc")
                .takes_value(true)
                .multiple(true)
                .help(
                    "Zero or more patterns matching files to include in the commit.",
                ),
        )
        .arg(
            Arg::with_name("EXCLUDE")
                .short("e")
                .long("exc")
                .takes_value(true)
                .multiple(true)
                .help(
                    "Zero or more patterns matching files to exclude from the commit.",
                ),
        )
        .arg(Arg::with_name("MESSAGE").index(1).required(true).help(
            "The commit message.",
        ))
}

pub fn go(repository: &mut Repository, matches: &ArgMatches) -> Result<()> {
    let include = if let Some(paths) = matches.values_of("INCLUDE") {
        let mut builder = GlobSetBuilder::new();
        for path in paths {
            builder.add(Glob::new(path)?);
        }
        Some(builder.build()?)
    } else {
        None
    };

    let exclude = if let Some(paths) = matches.values_of("EXCLUDE") {
        let mut builder = GlobSetBuilder::new();
        for path in paths {
            builder.add(Glob::new(path)?);
        }
        Some(builder.build()?)
    } else {
        None
    };

    let message = matches.value_of("MESSAGE").unwrap().to_owned();

    repository.index.update()?;

    let commit_hash = {
        let mut ctx = repository.local(Progress::new(None))?;
        let head = ctx.refs.head_hash().cloned().into_iter().collect();
        ctx.hash_commit(
            include.as_ref(),
            exclude.as_ref(),
            head,
            message,
            Utc::now(),
        ).wait()?
    };

    repository.refs.head = Head::Detached(commit_hash);
    repository.index.iter_mut().for_each(
        |(_, entry)| entry.added = false,
    );

    Ok(())
}
<commit_msg>More work on commit<commit_after>use chrono::prelude::*;
use clap::{App, SubCommand, Arg, ArgMatches};
use futures::prelude::*;
use globset::{Glob, GlobSetBuilder};

use attaca::Repository;
use attaca::repository::Head;

use errors::*;
use trace::Progress;

pub fn command() -> App<'static, 'static> {
    SubCommand::with_name("commit")
        .help("Commit a change to the local repository.")
        .arg(
            Arg::with_name("INCLUDE")
                .short("i")
                .long("inc")
                .takes_value(true)
                .multiple(true)
                .help(
                    "Zero or more patterns matching files to include in the commit.",
                ),
        )
        .arg(
            Arg::with_name("EXCLUDE")
                .short("e")
                .long("exc")
                .takes_value(true)
                .multiple(true)
                .help(
                    "Zero or more patterns matching files to exclude from the commit.",
                ),
        )
        .arg(Arg::with_name("MESSAGE").index(1).required(true).help(
            "The commit message.",
        ))
}

pub fn go(repository: &mut Repository, matches: &ArgMatches) -> Result<()> {
    let include = if let Some(paths) = matches.values_of("INCLUDE") {
        let mut builder = GlobSetBuilder::new();
        for path in paths {
            builder.add(Glob::new(path)?);
        }
        Some(builder.build()?)
    } else {
        None
    };

    let exclude = if let Some(paths) = matches.values_of("EXCLUDE") {
        let mut builder = GlobSetBuilder::new();
        for path in paths {
            builder.add(Glob::new(path)?);
        }
        Some(builder.build()?)
    } else {
        None
    };

    let message = matches.value_of("MESSAGE").unwrap().to_owned();

    repository.index.update()?;

    let commit_hash = {
        let mut ctx = repository.local(Progress::new(None))?;
        let head = ctx.refs.head().cloned().into_iter().collect();

        ctx.hash_commit(
            include.as_ref(),
            exclude.as_ref(),
            head,
            message,
            Utc::now(),
        ).join(ctx.close())
            .wait()?
            .0
    };

    repository.refs.head = Head::Detached(commit_hash);
    repository.index.iter_mut().for_each(
        |(_, entry)| entry.added = false,
    );

    Ok(())
}
<|endoftext|>