<commit_before>//! # Lucet Runtime for Sandboxed WebAssembly Applications
//!
//! This crate runs programs that were compiled with the `lucetc` WebAssembly to native code
//! compiler. It provides an interface for modules to be loaded from shared object files (see
//! `DlModule`), and for hosts to provide specialized functionality to guests (see
//! `Instance::embed_ctx()`).
//!
//! The runtime is a critical part of the safety and security story for Lucet. While the semantics
//! of WebAssembly and the `lucetc` compiler provide many guarantees, the runtime must be correct in
//! order for the assumptions of those guarantees to hold. For example, the runtime uses guard pages
//! to ensure that any attempts by guest programs to access memory past the end of the guest heap are
//! safely caught.
//!
//! The runtime is also extensible, and some of the key types are defined as traits for
//! flexibility. See the `lucet-runtime-internals` crate for details.
//!
//! ## Running a Lucet Program
//!
//! There are a few essential types for using the runtime:
//!
//! - [`Instance`](struct.Instance.html): a Lucet program, together with its dedicated memory and
//! signal handlers. Users of this API never own an `Instance` directly, but can own the
//! [`InstanceHandle`](struct.InstanceHandle.html) smart pointer.
//!
//! - [`Region`](trait.Region.html): the memory from which instances are created. This crate
//! includes [`MmapRegion`](struct.MmapRegion.html), an implementation backed by `mmap`.
//!
//! - [`Limits`](struct.Limits.html): upper bounds for the resources a Lucet instance may
//! consume. These may be larger or smaller than the limits described in the WebAssembly module
//! itself; the smaller limit is always enforced.
//!
//! - [`Module`](trait.Module.html): the read-only parts of a Lucet program, including its code and
//! initial heap configuration. This crate includes [`DlModule`](struct.DlModule.html), an
//! implementation backed by dynamic loading of shared objects.
//!
//! - [`Val`](enum.Val.html): an enum describing values in WebAssembly, used to provide
//! arguments. These can be created using `From` implementations of primitive types, for example
//! `5u64.into()` in the example below.
//!
//! - [`UntypedRetVal`](struct.UntypedRetVal.html): values returned from WebAssembly
//! functions. These must be interpreted at the correct type by the user via `From` implementations
//! or `retval.as_T()` methods, for example `u64::from(retval)` in the example below.
//!
//! To run a Lucet program, you start by creating a region, capable of backing a number of
//! instances. You then load a module and then create a new instance using the region and the
//! module. You can then run any of the functions that the Lucet program exports, retrieve return
//! values from those functions, and access the linear memory of the guest.
//!
//! ```no_run
//! use lucet_runtime::{DlModule, Limits, MmapRegion, Region};
//!
//! let module = DlModule::load("/my/lucet/module.so").unwrap();
//! let region = MmapRegion::create(1, &Limits::default()).unwrap();
//! let mut inst = region.new_instance(module).unwrap();
//!
//! let retval = inst.run(b"factorial", &[5u64.into()]).unwrap();
//! assert_eq!(u64::from(retval), 120u64);
//! ```
//!
//! ## Embedding With Hostcalls
//!
//! A "hostcall" is a function called by WebAssembly that is not defined in WebAssembly. Since
//! WebAssembly is such a minimal language, hostcalls are required for Lucet programs to do anything
//! interesting with the outside world. For example, in Fastly's [Terrarium
//! demo](https://wasm.fastly-labs.com/), hostcalls are provided for manipulating HTTP requests,
//! accessing a key/value store, etc.
//!
//! Some simple hostcalls can be implemented simply as an exported C function that takes an opaque
//! pointer argument (usually called `vmctx`). Hostcalls that require access to some underlying
//! state, such as the key/value store in Terrarium, can access a custom embedder context through
//! `vmctx`. For example, to make a `u32` available to hostcalls:
//!
//! ```no_run
//! use lucet_runtime::{DlModule, Limits, MmapRegion, Region};
//! use lucet_runtime::vmctx::{Vmctx, lucet_vmctx};
//!
//! struct MyContext { x: u32 }
//!
//! #[no_mangle]
//! unsafe extern "C" fn foo(vmctx: *mut lucet_vmctx) {
//!     let mut vmctx = Vmctx::from_raw(vmctx);
//!     let hostcall_context = vmctx
//!         .get_embed_ctx_mut::<MyContext>();
//!     hostcall_context.x = 42;
//! }
//!
//! let module = DlModule::load("/my/lucet/module.so").unwrap();
//! let region = MmapRegion::create(1, &Limits::default()).unwrap();
//! let mut inst = region
//!     .new_instance_builder(module)
//!     .with_embed_ctx(MyContext { x: 0 })
//!     .build()
//!     .unwrap();
//!
//! inst.run(b"call_foo", &[]).unwrap();
//!
//! let context_after = inst.get_embed_ctx::<MyContext>().unwrap();
//! assert_eq!(context_after.x, 42);
//! ```
//!
//! The embedder context is backed by a structure that can hold a single value of any type. Rust
//! embedders should add their own custom state type (like `MyContext` above) for any context they
//! require, rather than using a common type (such as the `u32`) from the standard library. This
//! avoids collisions between libraries, and allows for easy composition of embeddings.
//!
//! For C-based embedders, the type `*mut libc::c_void` is privileged as the only type that the C
//! API provides. The following example shows how a Rust embedder can initialize a C-compatible
//! context:
//!
//! ```no_run
//! use lucet_runtime::{DlModule, Limits, MmapRegion, Region};
//!
//! let module = DlModule::load("/my/lucet/module.so").unwrap();
//! let region = MmapRegion::create(1, &Limits::default()).unwrap();
//! #[repr(C)]
//! struct MyForeignContext { _unused: u8 };
//! let mut foreign_ctx = Box::into_raw(Box::new(MyForeignContext{ _unused: 0 }));
//! let mut inst = region
//!     .new_instance_builder(module)
//!     .with_embed_ctx(foreign_ctx as *mut libc::c_void)
//!     .build()
//!     .unwrap();
//!
//! inst.run(b"main", &[]).unwrap();
//!
//! // clean up embedder context
//! drop(inst);
//! // foreign_ctx must outlive inst, but then must be turned back into a box
//! // in order to drop.
//! unsafe { Box::from_raw(foreign_ctx) };
//! ```
//!
//! ## Custom Signal Handlers
//!
//! Since Lucet programs are run as native machine code, signals such as `SIGSEGV` and `SIGFPE` can
//! arise during execution. Rather than letting these signals bring down the entire process, the
//! Lucet runtime installs alternate signal handlers that limit the effects to just the instance
//! that raised the signal.
//!
//! By default, the signal handler sets the instance state to `State::Fault` and returns early from
//! the call to `Instance::run()`. You can, however, implement custom error recovery and logging
//! behavior by defining new signal handlers on a per-instance basis. For example, the following
//! signal handler increments a counter of signals it has seen before setting the fault state:
//!
//! ```no_run
//! use lucet_runtime::{
//!     DlModule, Error, Instance, Limits, MmapRegion, Region, SignalBehavior, TrapCode
//! };
//! use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
//!
//! static SIGNAL_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
//!
//! fn signal_handler_count(
//!     _inst: &Instance,
//!     _trapcode: &TrapCode,
//!     _signum: libc::c_int,
//!     _siginfo_ptr: *const libc::siginfo_t,
//!     _ucontext_ptr: *const libc::c_void,
//! ) -> SignalBehavior {
//!     SIGNAL_COUNT.fetch_add(1, Ordering::SeqCst);
//!     SignalBehavior::Default
//! }
//!
//! let module = DlModule::load("/my/lucet/module.so").unwrap();
//! let region = MmapRegion::create(1, &Limits::default()).unwrap();
//! let mut inst = region.new_instance(module).unwrap();
//!
//! // install the handler
//! inst.set_signal_handler(signal_handler_count);
//!
//! match inst.run(b"raise_a_signal", &[]) {
//!     Err(Error::RuntimeFault(_)) => {
//!         println!("I've now handled {} signals!", SIGNAL_COUNT.load(Ordering::SeqCst));
//!     }
//!     res => panic!("unexpected result: {:?}", res),
//! }
//! ```
//!
//! When implementing custom signal handlers for the Lucet runtime, the usual caveats about signal
//! safety apply: see
//! [`signal-safety(7)`](http://man7.org/linux/man-pages/man7/signal-safety.7.html).
//!
//! ## Interaction With Host Signal Handlers
//!
//! Great care must be taken if host application installs or otherwise modifies signal handlers
//! anywhere in the process. Lucet installs handlers for `SIGBUS`, `SIGFPE`, `SIGILL`, and `SIGSEGV`
//! when the first Lucet instance begins running, and restores the preëxisting handlers when the
//! last Lucet instance terminates. During this time, other threads in the host process *must not*
//! modify those signal handlers, since signal handlers can only be installed on a process-wide
//! basis.
//!
//! Despite this limitation, Lucet is designed to compose with other signal handlers in the host
//! program. If one of the above signals is caught by the Lucet signal handler, but that thread is
//! not currently running a Lucet instance, the saved host signal handler is called. This means
//! that, for example, a `SIGSEGV` on a non-Lucet thread of a host program will still likely abort
//! the entire process.

pub use lucet_runtime_internals::alloc::Limits;
pub use lucet_runtime_internals::error::Error;
pub use lucet_runtime_internals::instance::{
    FaultDetails, Instance, InstanceHandle, SignalBehavior, TerminationDetails,
};
pub use lucet_runtime_internals::module::{DlModule, Module};
pub use lucet_runtime_internals::region::mmap::MmapRegion;
pub use lucet_runtime_internals::region::{InstanceBuilder, Region};
pub use lucet_runtime_internals::trapcode::{TrapCode, TrapCodeType};
pub use lucet_runtime_internals::val::{UntypedRetVal, Val};
pub use lucet_runtime_internals::WASM_PAGE_SIZE;

pub mod vmctx {
    //! Functions for manipulating instances from hostcalls.
    //!
    //! The Lucet compiler inserts an extra `*mut lucet_vmctx` argument to all functions defined and
    //! called by WebAssembly code. Through this pointer, code running in the guest context can
    //! access and manipulate the instance and its structures. These functions are intended for use
    //! in hostcall implementations, and must only be used from within a running guest.
    //!
    //! # Panics
    //!
    //! All of the `Vmctx` methods will panic if the `Vmctx` was not created from a valid pointer
    //! associated with a running instance. This should never occur if run in guest code on the
    //! pointer argument inserted by the compiler.
    pub use lucet_runtime_internals::vmctx::{lucet_vmctx, Vmctx};
}

/// Call this if you're having trouble with `lucet_*` symbols not being exported.
///
/// This is pretty hackish; we will hopefully be able to avoid this altogether once [this
/// issue](https://github.com/rust-lang/rust/issues/58037) is addressed.
#[no_mangle]
pub extern "C" fn lucet_internal_ensure_linked() {
    lucet_runtime_internals::vmctx::vmctx_capi_init();
}
<commit_msg>wibble<commit_after>//! # Lucet Runtime for Sandboxed WebAssembly Applications
//!
//! This crate runs programs that were compiled with the `lucetc` WebAssembly to native code
//! compiler. It provides an interface for modules to be loaded from shared object files (see
//! `DlModule`), and for hosts to provide specialized functionality to guests (see
//! `Instance::embed_ctx()`).
//!
//! The runtime is a critical part of the safety and security story for Lucet. While the semantics
//! of WebAssembly and the `lucetc` compiler provide many guarantees, the runtime must be correct in
//! order for the assumptions of those guarantees to hold. For example, the runtime uses guard pages
//! to ensure that any attempts by guest programs to access memory past the end of the guest heap are
//! safely caught.
//!
//! The runtime is also extensible, and some of the key types are defined as traits for
//! flexibility. See the `lucet-runtime-internals` crate for details.
//!
//! ## Running a Lucet Program
//!
//! There are a few essential types for using the runtime:
//!
//! - [`Instance`](struct.Instance.html): a Lucet program, together with its dedicated memory and
//! signal handlers. Users of this API never own an `Instance` directly, but can own the
//! [`InstanceHandle`](struct.InstanceHandle.html) smart pointer.
//!
//! - [`Region`](trait.Region.html): the memory from which instances are created. This crate
//! includes [`MmapRegion`](struct.MmapRegion.html), an implementation backed by `mmap`.
//!
//! - [`Limits`](struct.Limits.html): upper bounds for the resources a Lucet instance may
//! consume. These may be larger or smaller than the limits described in the WebAssembly module
//! itself; the smaller limit is always enforced.
//!
//! - [`Module`](trait.Module.html): the read-only parts of a Lucet program, including its code and
//! initial heap configuration. This crate includes [`DlModule`](struct.DlModule.html), an
//! implementation backed by dynamic loading of shared objects.
//!
//! - [`Val`](enum.Val.html): an enum describing values in WebAssembly, used to provide
//! arguments. These can be created using `From` implementations of primitive types, for example
//! `5u64.into()` in the example below.
//!
//! - [`UntypedRetVal`](struct.UntypedRetVal.html): values returned from WebAssembly
//! functions. These must be interpreted at the correct type by the user via `From` implementations
//! or `retval.as_T()` methods, for example `u64::from(retval)` in the example below.
//!
//! To run a Lucet program, you start by creating a region, capable of backing a number of
//! instances. You then load a module and then create a new instance using the region and the
//! module. You can then run any of the functions that the Lucet program exports, retrieve return
//! values from those functions, and access the linear memory of the guest.
//!
//! ```no_run
//! use lucet_runtime::{DlModule, Limits, MmapRegion, Region};
//!
//! let module = DlModule::load("/my/lucet/module.so").unwrap();
//! let region = MmapRegion::create(1, &Limits::default()).unwrap();
//! let mut inst = region.new_instance(module).unwrap();
//!
//! let retval = inst.run(b"factorial", &[5u64.into()]).unwrap();
//! assert_eq!(u64::from(retval), 120u64);
//! ```
//!
//! ## Embedding With Hostcalls
//!
//! A "hostcall" is a function called by WebAssembly that is not defined in WebAssembly. Since
//! WebAssembly is such a minimal language, hostcalls are required for Lucet programs to do anything
//! interesting with the outside world. For example, in Fastly's [Terrarium
//! demo](https://wasm.fastly-labs.com/), hostcalls are provided for manipulating HTTP requests,
//! accessing a key/value store, etc.
//!
//! Some simple hostcalls can be implemented simply as an exported C function that takes an opaque
//! pointer argument (usually called `vmctx`). Hostcalls that require access to some underlying
//! state, such as the key/value store in Terrarium, can access a custom embedder context through
//! `vmctx`. For example, to make a `u32` available to hostcalls:
//!
//! ```no_run
//! use lucet_runtime::{DlModule, Limits, MmapRegion, Region};
//! use lucet_runtime::vmctx::{Vmctx, lucet_vmctx};
//!
//! struct MyContext { x: u32 }
//!
//! #[no_mangle]
//! unsafe extern "C" fn foo(vmctx: *mut lucet_vmctx) {
//!     let mut vmctx = Vmctx::from_raw(vmctx);
//!     let hostcall_context = vmctx
//!         .get_embed_ctx_mut::<MyContext>();
//!     hostcall_context.x = 42;
//! }
//!
//! let module = DlModule::load("/my/lucet/module.so").unwrap();
//! let region = MmapRegion::create(1, &Limits::default()).unwrap();
//! let mut inst = region
//!     .new_instance_builder(module)
//!     .with_embed_ctx(MyContext { x: 0 })
//!     .build()
//!     .unwrap();
//!
//! inst.run(b"call_foo", &[]).unwrap();
//!
//! let context_after = inst.get_embed_ctx::<MyContext>().unwrap();
//! assert_eq!(context_after.x, 42);
//! ```
//!
//! The embedder context is backed by a structure that can hold a single value of any type. Rust
//! embedders should add their own custom state type (like `MyContext` above) for any context they
//! require, rather than using a common type (such as the `u32`) from the standard library. This
//! avoids collisions between libraries, and allows for easy composition of embeddings.
//!
//! For C-based embedders, the type `*mut libc::c_void` is privileged as the only type that the C
//! API provides. The following example shows how a Rust embedder can initialize a C-compatible
//! context:
//!
//! ```no_run
//! use lucet_runtime::{DlModule, Limits, MmapRegion, Region};
//!
//! let module = DlModule::load("/my/lucet/module.so").unwrap();
//! let region = MmapRegion::create(1, &Limits::default()).unwrap();
//! #[repr(C)]
//! struct MyForeignContext { x: u32 };
//! let mut foreign_ctx = Box::into_raw(Box::new(MyForeignContext{ x: 0 }));
//! let mut inst = region
//!     .new_instance_builder(module)
//!     .with_embed_ctx(foreign_ctx as *mut libc::c_void)
//!     .build()
//!     .unwrap();
//!
//! inst.run(b"main", &[]).unwrap();
//!
//! // clean up embedder context
//! drop(inst);
//! // foreign_ctx must outlive inst, but then must be turned back into a box
//! // in order to drop.
//! unsafe { Box::from_raw(foreign_ctx) };
//! ```
//!
//! ## Custom Signal Handlers
//!
//! Since Lucet programs are run as native machine code, signals such as `SIGSEGV` and `SIGFPE` can
//! arise during execution. Rather than letting these signals bring down the entire process, the
//! Lucet runtime installs alternate signal handlers that limit the effects to just the instance
//! that raised the signal.
//!
//! By default, the signal handler sets the instance state to `State::Fault` and returns early from
//! the call to `Instance::run()`. You can, however, implement custom error recovery and logging
//! behavior by defining new signal handlers on a per-instance basis. For example, the following
//! signal handler increments a counter of signals it has seen before setting the fault state:
//!
//! ```no_run
//! use lucet_runtime::{
//!     DlModule, Error, Instance, Limits, MmapRegion, Region, SignalBehavior, TrapCode
//! };
//! use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
//!
//! static SIGNAL_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
//!
//! fn signal_handler_count(
//!     _inst: &Instance,
//!     _trapcode: &TrapCode,
//!     _signum: libc::c_int,
//!     _siginfo_ptr: *const libc::siginfo_t,
//!     _ucontext_ptr: *const libc::c_void,
//! ) -> SignalBehavior {
//!     SIGNAL_COUNT.fetch_add(1, Ordering::SeqCst);
//!     SignalBehavior::Default
//! }
//!
//! let module = DlModule::load("/my/lucet/module.so").unwrap();
//! let region = MmapRegion::create(1, &Limits::default()).unwrap();
//! let mut inst = region.new_instance(module).unwrap();
//!
//! // install the handler
//! inst.set_signal_handler(signal_handler_count);
//!
//! match inst.run(b"raise_a_signal", &[]) {
//!     Err(Error::RuntimeFault(_)) => {
//!         println!("I've now handled {} signals!", SIGNAL_COUNT.load(Ordering::SeqCst));
//!     }
//!     res => panic!("unexpected result: {:?}", res),
//! }
//! ```
//!
//! When implementing custom signal handlers for the Lucet runtime, the usual caveats about signal
//! safety apply: see
//! [`signal-safety(7)`](http://man7.org/linux/man-pages/man7/signal-safety.7.html).
//!
//! ## Interaction With Host Signal Handlers
//!
//! Great care must be taken if host application installs or otherwise modifies signal handlers
//! anywhere in the process. Lucet installs handlers for `SIGBUS`, `SIGFPE`, `SIGILL`, and `SIGSEGV`
//! when the first Lucet instance begins running, and restores the preëxisting handlers when the
//! last Lucet instance terminates. During this time, other threads in the host process *must not*
//! modify those signal handlers, since signal handlers can only be installed on a process-wide
//! basis.
//!
//! Despite this limitation, Lucet is designed to compose with other signal handlers in the host
//! program. If one of the above signals is caught by the Lucet signal handler, but that thread is
//! not currently running a Lucet instance, the saved host signal handler is called. This means
//! that, for example, a `SIGSEGV` on a non-Lucet thread of a host program will still likely abort
//! the entire process.

pub use lucet_runtime_internals::alloc::Limits;
pub use lucet_runtime_internals::error::Error;
pub use lucet_runtime_internals::instance::{
    FaultDetails, Instance, InstanceHandle, SignalBehavior, TerminationDetails,
};
pub use lucet_runtime_internals::module::{DlModule, Module};
pub use lucet_runtime_internals::region::mmap::MmapRegion;
pub use lucet_runtime_internals::region::{InstanceBuilder, Region};
pub use lucet_runtime_internals::trapcode::{TrapCode, TrapCodeType};
pub use lucet_runtime_internals::val::{UntypedRetVal, Val};
pub use lucet_runtime_internals::WASM_PAGE_SIZE;

pub mod vmctx {
    //! Functions for manipulating instances from hostcalls.
    //!
    //! The Lucet compiler inserts an extra `*mut lucet_vmctx` argument to all functions defined and
    //! called by WebAssembly code. Through this pointer, code running in the guest context can
    //! access and manipulate the instance and its structures. These functions are intended for use
    //! in hostcall implementations, and must only be used from within a running guest.
    //!
    //! # Panics
    //!
    //! All of the `Vmctx` methods will panic if the `Vmctx` was not created from a valid pointer
    //! associated with a running instance. This should never occur if run in guest code on the
    //! pointer argument inserted by the compiler.
    pub use lucet_runtime_internals::vmctx::{lucet_vmctx, Vmctx};
}

/// Call this if you're having trouble with `lucet_*` symbols not being exported.
///
/// This is pretty hackish; we will hopefully be able to avoid this altogether once [this
/// issue](https://github.com/rust-lang/rust/issues/58037) is addressed.
#[no_mangle]
pub extern "C" fn lucet_internal_ensure_linked() {
    lucet_runtime_internals::vmctx::vmctx_capi_init();
}
<|endoftext|>


<commit_before>// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

//! This is the default topology. It's most useful for applications that stand alone, or that don't
//! share state between one another.
//!
//! ![Standalone Topology](../../images/standalone.png)
//!
//! * **Initializing**: Initializes the service by running the `init` hook if present.
//! * **Starting**: Starts the service under `runsv`, and starts a thread to process output and
//! handle errors.
//! * **Running**: The state for the 'normal' operating condition.

use std::thread;
use std::process::{Command, Stdio, Child};
use std::io::prelude::*;

use hcore::fs::SVC_PATH;

use error::{Error, Result, SupError};
use package::Package;
use state_machine::StateMachine;
use topology::{self, State, Worker};
use config::Config;

/// Sets up the topology and calls run_internal.
///
/// Add's the state transitions to the state machine, sets up the signal handlers, and runs the
/// `topology::run_internal` function.
pub fn run(package: Package, config: &Config) -> Result<()> {
    let mut worker = try!(Worker::new(package, String::from("standalone"), config));
    let mut sm: StateMachine<State, Worker, SupError> = StateMachine::new(State::Initializing);
    sm.add_dispatch(State::Initializing, state_initializing);
    sm.add_dispatch(State::Starting, state_starting);
    sm.add_dispatch(State::Running, state_running);
    topology::run_internal(&mut sm, &mut worker)
}

/// Initialize the service.
pub fn state_initializing(worker: &mut Worker) -> Result<(State, u64)> {
    let service_config = worker.service_config.read().unwrap();
    let package = worker.package.read().unwrap();
    match package.initialize(&service_config) {
        Ok(()) => Ok((State::Starting, 0)),
        Err(e) => Err(e),
    }
}

/// Start the service.
///
/// 1. Finds the package
/// 1. Starts the package `run` script
/// 1. Spawns the supervisor thread
///
/// # Failures
///
/// * If we cannot find the package
/// * If we cannot start the supervisor
pub fn state_starting(worker: &mut Worker) -> Result<(State, u64)> {
    {
        let mut supervisor = worker.supervisor.write().unwrap();
        try!(supervisor.start());
    }
    Ok((State::Running, 0))
}

pub fn state_running(worker: &mut Worker) -> Result<(State, u64)> {
    if let Some(state) = worker.return_state {
        Ok((state, 0))
    } else {
        Ok((State::Running, 0))
    }
}
<commit_msg>Remove unneeded imports.<commit_after>// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

//! This is the default topology. It's most useful for applications that stand alone, or that don't
//! share state between one another.
//!
//! ![Standalone Topology](../../images/standalone.png)
//!
//! * **Initializing**: Initializes the service by running the `init` hook if present.
//! * **Starting**: Starts the service under `runsv`, and starts a thread to process output and
//! handle errors.
//! * **Running**: The state for the 'normal' operating condition.

use error::{Result, SupError};
use package::Package;
use state_machine::StateMachine;
use topology::{self, State, Worker};
use config::Config;

/// Sets up the topology and calls run_internal.
///
/// Add's the state transitions to the state machine, sets up the signal handlers, and runs the
/// `topology::run_internal` function.
pub fn run(package: Package, config: &Config) -> Result<()> {
    let mut worker = try!(Worker::new(package, String::from("standalone"), config));
    let mut sm: StateMachine<State, Worker, SupError> = StateMachine::new(State::Initializing);
    sm.add_dispatch(State::Initializing, state_initializing);
    sm.add_dispatch(State::Starting, state_starting);
    sm.add_dispatch(State::Running, state_running);
    topology::run_internal(&mut sm, &mut worker)
}

/// Initialize the service.
pub fn state_initializing(worker: &mut Worker) -> Result<(State, u64)> {
    let service_config = worker.service_config.read().unwrap();
    let package = worker.package.read().unwrap();
    match package.initialize(&service_config) {
        Ok(()) => Ok((State::Starting, 0)),
        Err(e) => Err(e),
    }
}

/// Start the service.
///
/// 1. Finds the package
/// 1. Starts the package `run` script
/// 1. Spawns the supervisor thread
///
/// # Failures
///
/// * If we cannot find the package
/// * If we cannot start the supervisor
pub fn state_starting(worker: &mut Worker) -> Result<(State, u64)> {
    {
        let mut supervisor = worker.supervisor.write().unwrap();
        try!(supervisor.start());
    }
    Ok((State::Running, 0))
}

pub fn state_running(worker: &mut Worker) -> Result<(State, u64)> {
    if let Some(state) = worker.return_state {
        Ok((state, 0))
    } else {
        Ok((State::Running, 0))
    }
}
<|endoftext|>


<commit_before>#[inline]
pub fn l1(x: &[f64]) -> f64 {
    x.iter().fold(0.0, |acc, v| acc + v.abs())
}

#[inline]
pub fn l2(x: &[f64]) -> f64 {
    x.iter().fold(0.0, |acc, v| acc + (v*v).abs()).sqrt()
}

#[inline]
pub fn lp(x: &[f64], p: u8) -> f64 {
    x.iter().fold(0.0, |acc, v| acc + v.abs().powi(p as i32)).powf((p as f64).recip())
}

#[inline]
pub fn linf(x: &[f64]) -> f64 {
    x.iter().fold(0.0, |max, v| {
        let av = v.abs();

        if av > max {
            av
        } else {
            max
        }
    })
}
<commit_msg>docs(geometry): add documentation to geometry::norms<commit_after>/// Computes the L1 norm.
#[inline]
pub fn l1(x: &[f64]) -> f64 {
    x.iter().fold(0.0, |acc, v| acc + v.abs())
}

/// Computes the L2 norm.
#[inline]
pub fn l2(x: &[f64]) -> f64 {
    x.iter().fold(0.0, |acc, v| acc + (v*v).abs()).sqrt()
}

/// Computes the Lp norm.
#[inline]
pub fn lp(x: &[f64], p: u8) -> f64 {
    x.iter().fold(0.0, |acc, v| acc + v.abs().powi(p as i32)).powf((p as f64).recip())
}

/// Computes the infinity norm.
#[inline]
pub fn linf(x: &[f64]) -> f64 {
    x.iter().fold(0.0, |max, v| {
        let av = v.abs();

        if av > max {
            av
        } else {
            max
        }
    })
}
<|endoftext|>


<commit_before>use super::mpz::{mpz_struct, Mpz, mpz_ptr, mpz_srcptr};
use super::mpf::{Mpf, mpf_srcptr};
use ffi::*;
use libc::{c_double, c_int, c_ulong};
use std::convert::{From, Into};
use std::mem::uninitialized;
use std::fmt;
use std::cmp::Ordering::{self, Greater, Less, Equal};
use std::ops::{Div, DivAssign, Mul, MulAssign, Add, AddAssign, Sub, SubAssign, Neg};

#[repr(C)]
pub struct mpq_struct {
    _mp_num: mpz_struct,
    _mp_den: mpz_struct
}

pub type mpq_srcptr = *const mpq_struct;
pub type mpq_ptr = *mut mpq_struct;

#[link(name = "gmp")]
extern "C" {
    fn __gmpq_init(x: mpq_ptr);
    fn __gmpq_clear(x: mpq_ptr);
    fn __gmpq_set(rop: mpq_ptr, op: mpq_srcptr);
    fn __gmpq_set_z(rop: mpq_ptr, op: mpz_srcptr);
    fn __gmpq_set_ui(rop: mpq_ptr, op1: c_ulong, op2: c_ulong);
    fn __gmpq_set_d(rop: mpq_ptr, op: c_double);
    fn __gmpq_set_f(rop: mpq_ptr, op: mpf_srcptr);
    fn __gmpq_cmp(op1: mpq_srcptr, op2: mpq_srcptr) -> c_int;
    fn __gmpq_cmp_ui(op1: mpq_srcptr, num2: c_ulong, den2: c_ulong) -> c_int;
    fn __gmpq_equal(op1: mpq_srcptr, op2: mpq_srcptr) -> c_int;
    fn __gmpq_add(sum: mpq_ptr, addend1: mpq_srcptr, addend2: mpq_srcptr);
    fn __gmpq_sub(difference: mpq_ptr, minuend: mpq_srcptr, subtrahend: mpq_srcptr);
    fn __gmpq_mul(product: mpq_ptr, multiplier: mpq_srcptr, multiplicand: mpq_srcptr);
    fn __gmpq_div(product: mpq_ptr, multiplier: mpq_srcptr, multiplicand: mpq_srcptr);
    fn __gmpq_neg(negated_operand: mpq_ptr, operand: mpq_srcptr);
    fn __gmpq_abs(rop: mpq_ptr, op: mpq_srcptr);
    fn __gmpq_inv(inverted_number: mpq_ptr, number: mpq_srcptr);
    fn __gmpq_get_num(numerator: mpz_ptr, rational: mpq_srcptr);
    fn __gmpq_get_den(denominator: mpz_ptr, rational: mpq_srcptr);
    fn __gmpq_set_num(rational: mpq_ptr, numerator: mpz_srcptr);
    fn __gmpq_set_den(rational: mpq_ptr, denominator: mpz_srcptr);
    fn __gmpq_canonicalize(rational: mpq_ptr);
    fn __gmpq_get_d(rational: mpq_srcptr) -> c_double;
}

pub struct Mpq {
    mpq: mpq_struct,
}

unsafe impl Send for Mpq { }

impl Drop for Mpq {
    fn drop(&mut self) { unsafe { __gmpq_clear(&mut self.mpq) } }
}

impl Mpq {
    pub unsafe fn inner(&self) -> mpq_srcptr {
        &self.mpq
    }

    pub unsafe fn inner_mut(&mut self) -> mpq_ptr {
        &mut self.mpq
    }

    pub fn new() -> Mpq {
        unsafe {
            let mut mpq = uninitialized();
            __gmpq_init(&mut mpq);
            Mpq { mpq: mpq }
        }
    }

    pub fn ratio(num: &Mpz, den: &Mpz) -> Mpq {
        unsafe {
            let mut res = Mpq::new();
            __gmpq_set_num(&mut res.mpq, num.inner());
            __gmpq_set_den(&mut res.mpq, den.inner());
            res
        }
    }

    pub fn canonicalize(&mut self) {
        unsafe {
            __gmpq_canonicalize(&mut self.mpq);
        }
    }

    pub fn set(&mut self, other: &Mpq) {
        unsafe { __gmpq_set(&mut self.mpq, &other.mpq) }
    }

    pub fn set_z(&mut self, other: &Mpz) {
        unsafe { __gmpq_set_z(&mut self.mpq, other.inner()) }
    }

    pub fn set_d(&mut self, other: f64) {
        unsafe { __gmpq_set_d(&mut self.mpq, other) }
    }

    pub fn set_f(&mut self, other: &Mpf) {
        unsafe { __gmpq_set_f(&mut self.mpq, other.inner()) }
    }

    pub fn get_num(&self) -> Mpz {
        unsafe {
            let mut res = Mpz::new();
            __gmpq_get_num(res.inner_mut(), &self.mpq);
            res
        }
    }

    pub fn get_den(&self) -> Mpz {
        unsafe {
            let mut res = Mpz::new();
            __gmpq_get_den(res.inner_mut(), &self.mpq);
            res
        }
    }

    pub fn abs(&self) -> Mpq {
        unsafe {
            let mut res = Mpq::new();
            __gmpq_abs(&mut res.mpq, &self.mpq);
            res
        }
    }

    pub fn invert(&self) -> Mpq {
        unsafe {
            if self.is_zero() {
                panic!("divide by zero")
            }

            let mut res = Mpq::new();
            __gmpq_inv(&mut res.mpq, &self.mpq);
            res
        }
    }

    pub fn floor(&self) -> Mpz {
        let mut res = Mpz::new();
        unsafe {
            __gmpz_fdiv_q(res.inner_mut(), &self.mpq._mp_num, &self.mpq._mp_den);
        }
        res
    }

    pub fn ceil(&self) -> Mpz {
        let mut res = Mpz::new();
        unsafe {
            __gmpz_cdiv_q(res.inner_mut(), &self.mpq._mp_num, &self.mpq._mp_den);
        }
        res
    }

    pub fn one() -> Mpq {
        let mut res = Mpq::new();
        unsafe { __gmpq_set_ui(&mut res.mpq, 1, 1) }
        res
    }

    pub fn zero() -> Mpq { Mpq::new() }
    pub fn is_zero(&self) -> bool {
        unsafe { __gmpq_cmp_ui(&self.mpq, 0, 1) == 0 }
    }
}

impl Clone for Mpq {
    fn clone(&self) -> Mpq {
        let mut res = Mpq::new();
        res.set(self);
        res
    }
}

impl Eq for Mpq { }
impl PartialEq for Mpq {
    fn eq(&self, other: &Mpq) -> bool {
        unsafe { __gmpq_equal(&self.mpq, &other.mpq) != 0 }
    }
}

impl Ord for Mpq {
    fn cmp(&self, other: &Mpq) -> Ordering {
        let cmp = unsafe { __gmpq_cmp(&self.mpq, &other.mpq) };
        if cmp == 0 {
            Equal
        } else if cmp < 0 {
            Less
        } else {
            Greater
        }
    }
}
impl PartialOrd for Mpq {
    fn partial_cmp(&self, other: &Mpq) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

macro_rules! div_guard {
    (Div, $what: expr) => {
        if $what.is_zero() {
            panic!("divide by zero")
        }
    };
    ($tr: ident, $what: expr) => {}
}

macro_rules! impl_oper {
    ($tr: ident, $meth: ident, $tr_assign: ident, $meth_assign: ident, $fun: ident) => {
        impl<'a> $tr<&'a Mpq> for Mpq {
            type Output = Mpq;
            #[inline]
            fn $meth(mut self, other: &Mpq) -> Mpq {
                self.$meth_assign(other);
                self
            }
        }

        impl<'a, 'b> $tr<&'a Mpq> for &'b Mpq {
            type Output = Mpq;
            fn $meth(self, other: &Mpq) -> Mpq {
                unsafe {
                    div_guard!($tr, *other);
                    let mut res = Mpq::new();
                    $fun(&mut res.mpq, &self.mpq, &other.mpq);
                    res
                }
            }
        }

        impl<'a> $tr_assign<Mpq> for Mpq {
            #[inline]
            fn $meth_assign(&mut self, other: Mpq) {
                self.$meth_assign(&other)
            }
        }

        impl<'a> $tr_assign<&'a Mpq> for Mpq {
            #[inline]
            fn $meth_assign(&mut self, other: &Mpq) {
                unsafe {
                    div_guard!($tr, *other);
                    $fun(&mut self.mpq, &self.mpq, &other.mpq)
                }
            }
        }
    }
}

impl_oper!(Add, add, AddAssign, add_assign, __gmpq_add);
impl_oper!(Sub, sub, SubAssign, sub_assign, __gmpq_sub);
impl_oper!(Mul, mul, MulAssign, mul_assign, __gmpq_mul);
impl_oper!(Div, div, DivAssign, div_assign, __gmpq_div);

impl<'b> Neg for &'b Mpq {
    type Output = Mpq;
    fn neg(self) -> Mpq {
        unsafe {
            let mut res = Mpq::new();
            __gmpq_neg(&mut res.mpq, &self.mpq);
            res
        }
    }
}

impl Neg for Mpq {
    type Output = Mpq;
    #[inline]
    fn neg(mut self) -> Mpq {
        unsafe {
            __gmpq_neg(&mut self.mpq, &self.mpq);
            self
        }
    }
}

impl Into<Option<i64>> for Mpq {
    fn into(self) -> Option<i64> {
        panic!("not implemented")
    }
}

impl Into<Option<u64>> for Mpq {
    fn into(self) -> Option<u64> {
        panic!("not implemented")
    }
}

impl Into<f64> for Mpq {
    fn into(self) -> f64 {
        unsafe {
            __gmpq_get_d(&self.mpq) as f64
        }
    }
}

impl From<Mpz> for Mpq {
    fn from(other: Mpz) -> Mpq {
        let mut res = Mpq::new();
        res.set_z(&other);
        res
    }
}

impl From<i64> for Mpq {
    fn from(other: i64) -> Mpq {
        From::<Mpz>::from(From::<i64>::from(other))
    }
}

impl From<i32> for Mpq {
    fn from(other: i32) -> Mpq {
        From::<Mpz>::from(From::<i32>::from(other))
    }
}

impl From<u64> for Mpq {
    fn from(other: u64) -> Mpq {
        From::<Mpz>::from(From::<u64>::from(other))
    }
}

impl From<u32> for Mpq {
    fn from(other: u32) -> Mpq {
        From::<Mpz>::from(From::<u32>::from(other))
    }
}

impl fmt::Debug for Mpq {
    /// Renders as `numer/denom`. If denom=1, renders as numer.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let numer = self.get_num();
        let denom = self.get_den();

        if denom == From::<i64>::from(1) {
            write!(f, "{}", numer)
        } else {
            write!(f, "{}/{}", numer, denom)
        }
    }
}

gen_overloads!(Mpq);
<commit_msg>Mpq: Implement op(&Mpq, Mpq) more efficiently<commit_after>use super::mpz::{mpz_struct, Mpz, mpz_ptr, mpz_srcptr};
use super::mpf::{Mpf, mpf_srcptr};
use ffi::*;
use libc::{c_double, c_int, c_ulong};
use std::convert::{From, Into};
use std::mem::uninitialized;
use std::fmt;
use std::cmp::Ordering::{self, Greater, Less, Equal};
use std::ops::{Div, DivAssign, Mul, MulAssign, Add, AddAssign, Sub, SubAssign, Neg};

#[repr(C)]
pub struct mpq_struct {
    _mp_num: mpz_struct,
    _mp_den: mpz_struct
}

pub type mpq_srcptr = *const mpq_struct;
pub type mpq_ptr = *mut mpq_struct;

#[link(name = "gmp")]
extern "C" {
    fn __gmpq_init(x: mpq_ptr);
    fn __gmpq_clear(x: mpq_ptr);
    fn __gmpq_set(rop: mpq_ptr, op: mpq_srcptr);
    fn __gmpq_set_z(rop: mpq_ptr, op: mpz_srcptr);
    fn __gmpq_set_ui(rop: mpq_ptr, op1: c_ulong, op2: c_ulong);
    fn __gmpq_set_d(rop: mpq_ptr, op: c_double);
    fn __gmpq_set_f(rop: mpq_ptr, op: mpf_srcptr);
    fn __gmpq_cmp(op1: mpq_srcptr, op2: mpq_srcptr) -> c_int;
    fn __gmpq_cmp_ui(op1: mpq_srcptr, num2: c_ulong, den2: c_ulong) -> c_int;
    fn __gmpq_equal(op1: mpq_srcptr, op2: mpq_srcptr) -> c_int;
    fn __gmpq_add(sum: mpq_ptr, addend1: mpq_srcptr, addend2: mpq_srcptr);
    fn __gmpq_sub(difference: mpq_ptr, minuend: mpq_srcptr, subtrahend: mpq_srcptr);
    fn __gmpq_mul(product: mpq_ptr, multiplier: mpq_srcptr, multiplicand: mpq_srcptr);
    fn __gmpq_div(product: mpq_ptr, multiplier: mpq_srcptr, multiplicand: mpq_srcptr);
    fn __gmpq_neg(negated_operand: mpq_ptr, operand: mpq_srcptr);
    fn __gmpq_abs(rop: mpq_ptr, op: mpq_srcptr);
    fn __gmpq_inv(inverted_number: mpq_ptr, number: mpq_srcptr);
    fn __gmpq_get_num(numerator: mpz_ptr, rational: mpq_srcptr);
    fn __gmpq_get_den(denominator: mpz_ptr, rational: mpq_srcptr);
    fn __gmpq_set_num(rational: mpq_ptr, numerator: mpz_srcptr);
    fn __gmpq_set_den(rational: mpq_ptr, denominator: mpz_srcptr);
    fn __gmpq_canonicalize(rational: mpq_ptr);
    fn __gmpq_get_d(rational: mpq_srcptr) -> c_double;
}

pub struct Mpq {
    mpq: mpq_struct,
}

unsafe impl Send for Mpq { }

impl Drop for Mpq {
    fn drop(&mut self) { unsafe { __gmpq_clear(&mut self.mpq) } }
}

impl Mpq {
    pub unsafe fn inner(&self) -> mpq_srcptr {
        &self.mpq
    }

    pub unsafe fn inner_mut(&mut self) -> mpq_ptr {
        &mut self.mpq
    }

    pub fn new() -> Mpq {
        unsafe {
            let mut mpq = uninitialized();
            __gmpq_init(&mut mpq);
            Mpq { mpq: mpq }
        }
    }

    pub fn ratio(num: &Mpz, den: &Mpz) -> Mpq {
        unsafe {
            let mut res = Mpq::new();
            __gmpq_set_num(&mut res.mpq, num.inner());
            __gmpq_set_den(&mut res.mpq, den.inner());
            res
        }
    }

    pub fn canonicalize(&mut self) {
        unsafe {
            __gmpq_canonicalize(&mut self.mpq);
        }
    }

    pub fn set(&mut self, other: &Mpq) {
        unsafe { __gmpq_set(&mut self.mpq, &other.mpq) }
    }

    pub fn set_z(&mut self, other: &Mpz) {
        unsafe { __gmpq_set_z(&mut self.mpq, other.inner()) }
    }

    pub fn set_d(&mut self, other: f64) {
        unsafe { __gmpq_set_d(&mut self.mpq, other) }
    }

    pub fn set_f(&mut self, other: &Mpf) {
        unsafe { __gmpq_set_f(&mut self.mpq, other.inner()) }
    }

    pub fn get_num(&self) -> Mpz {
        unsafe {
            let mut res = Mpz::new();
            __gmpq_get_num(res.inner_mut(), &self.mpq);
            res
        }
    }

    pub fn get_den(&self) -> Mpz {
        unsafe {
            let mut res = Mpz::new();
            __gmpq_get_den(res.inner_mut(), &self.mpq);
            res
        }
    }

    pub fn abs(&self) -> Mpq {
        unsafe {
            let mut res = Mpq::new();
            __gmpq_abs(&mut res.mpq, &self.mpq);
            res
        }
    }

    pub fn invert(&self) -> Mpq {
        unsafe {
            if self.is_zero() {
                panic!("divide by zero")
            }

            let mut res = Mpq::new();
            __gmpq_inv(&mut res.mpq, &self.mpq);
            res
        }
    }

    pub fn floor(&self) -> Mpz {
        let mut res = Mpz::new();
        unsafe {
            __gmpz_fdiv_q(res.inner_mut(), &self.mpq._mp_num, &self.mpq._mp_den);
        }
        res
    }

    pub fn ceil(&self) -> Mpz {
        let mut res = Mpz::new();
        unsafe {
            __gmpz_cdiv_q(res.inner_mut(), &self.mpq._mp_num, &self.mpq._mp_den);
        }
        res
    }

    pub fn one() -> Mpq {
        let mut res = Mpq::new();
        unsafe { __gmpq_set_ui(&mut res.mpq, 1, 1) }
        res
    }

    pub fn zero() -> Mpq { Mpq::new() }
    pub fn is_zero(&self) -> bool {
        unsafe { __gmpq_cmp_ui(&self.mpq, 0, 1) == 0 }
    }
}

impl Clone for Mpq {
    fn clone(&self) -> Mpq {
        let mut res = Mpq::new();
        res.set(self);
        res
    }
}

impl Eq for Mpq { }
impl PartialEq for Mpq {
    fn eq(&self, other: &Mpq) -> bool {
        unsafe { __gmpq_equal(&self.mpq, &other.mpq) != 0 }
    }
}

impl Ord for Mpq {
    fn cmp(&self, other: &Mpq) -> Ordering {
        let cmp = unsafe { __gmpq_cmp(&self.mpq, &other.mpq) };
        if cmp == 0 {
            Equal
        } else if cmp < 0 {
            Less
        } else {
            Greater
        }
    }
}
impl PartialOrd for Mpq {
    fn partial_cmp(&self, other: &Mpq) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

macro_rules! div_guard {
    (Div, $what: expr) => {
        if $what.is_zero() {
            panic!("divide by zero")
        }
    };
    ($tr: ident, $what: expr) => {}
}

macro_rules! impl_oper {
    ($tr: ident, $meth: ident, $tr_assign: ident, $meth_assign: ident, $fun: ident) => {
        impl $tr<Mpq> for Mpq {
            type Output = Mpq;
            #[inline]
            fn $meth(self, other: Mpq) -> Mpq {
                self.$meth(&other)
            }
        }

        impl<'a> $tr<&'a Mpq> for Mpq {
            type Output = Mpq;
            #[inline]
            fn $meth(mut self, other: &Mpq) -> Mpq {
                self.$meth_assign(other);
                self
            }
        }

        impl<'a> $tr<Mpq> for &'a Mpq {
            type Output = Mpq;
            #[inline]
            fn $meth(self, mut other: Mpq) -> Mpq {
                unsafe {
                    div_guard!($tr, other);
                    $fun(&mut other.mpq, &self.mpq, &other.mpq);
                    other
                }
            }
        }

        impl<'a, 'b> $tr<&'a Mpq> for &'b Mpq {
            type Output = Mpq;
            fn $meth(self, other: &Mpq) -> Mpq {
                unsafe {
                    div_guard!($tr, *other);
                    let mut res = Mpq::new();
                    $fun(&mut res.mpq, &self.mpq, &other.mpq);
                    res
                }
            }
        }

        impl<'a> $tr_assign<Mpq> for Mpq {
            #[inline]
            fn $meth_assign(&mut self, other: Mpq) {
                self.$meth_assign(&other)
            }
        }

        impl<'a> $tr_assign<&'a Mpq> for Mpq {
            #[inline]
            fn $meth_assign(&mut self, other: &Mpq) {
                unsafe {
                    div_guard!($tr, *other);
                    $fun(&mut self.mpq, &self.mpq, &other.mpq)
                }
            }
        }
    }
}

impl_oper!(Add, add, AddAssign, add_assign, __gmpq_add);
impl_oper!(Sub, sub, SubAssign, sub_assign, __gmpq_sub);
impl_oper!(Mul, mul, MulAssign, mul_assign, __gmpq_mul);
impl_oper!(Div, div, DivAssign, div_assign, __gmpq_div);

impl<'b> Neg for &'b Mpq {
    type Output = Mpq;
    fn neg(self) -> Mpq {
        unsafe {
            let mut res = Mpq::new();
            __gmpq_neg(&mut res.mpq, &self.mpq);
            res
        }
    }
}

impl Neg for Mpq {
    type Output = Mpq;
    #[inline]
    fn neg(mut self) -> Mpq {
        unsafe {
            __gmpq_neg(&mut self.mpq, &self.mpq);
            self
        }
    }
}

impl Into<Option<i64>> for Mpq {
    fn into(self) -> Option<i64> {
        panic!("not implemented")
    }
}

impl Into<Option<u64>> for Mpq {
    fn into(self) -> Option<u64> {
        panic!("not implemented")
    }
}

impl Into<f64> for Mpq {
    fn into(self) -> f64 {
        unsafe {
            __gmpq_get_d(&self.mpq) as f64
        }
    }
}

impl From<Mpz> for Mpq {
    fn from(other: Mpz) -> Mpq {
        let mut res = Mpq::new();
        res.set_z(&other);
        res
    }
}

impl From<i64> for Mpq {
    fn from(other: i64) -> Mpq {
        From::<Mpz>::from(From::<i64>::from(other))
    }
}

impl From<i32> for Mpq {
    fn from(other: i32) -> Mpq {
        From::<Mpz>::from(From::<i32>::from(other))
    }
}

impl From<u64> for Mpq {
    fn from(other: u64) -> Mpq {
        From::<Mpz>::from(From::<u64>::from(other))
    }
}

impl From<u32> for Mpq {
    fn from(other: u32) -> Mpq {
        From::<Mpz>::from(From::<u32>::from(other))
    }
}

impl fmt::Debug for Mpq {
    /// Renders as `numer/denom`. If denom=1, renders as numer.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let numer = self.get_num();
        let denom = self.get_den();

        if denom == From::<i64>::from(1) {
            write!(f, "{}", numer)
        } else {
            write!(f, "{}/{}", numer, denom)
        }
    }
}
<|endoftext|>


<commit_before>#![allow(non_camel_case_types)]

use libc::*;
use std::sync::{StaticMutex, MUTEX_INIT};
use std::error::Error;
use std::fmt;
use std::mem;
use std::ptr::null;

static NFQ_LOCK: StaticMutex = MUTEX_INIT;

#[derive(Debug)]
enum ErrorReason {
    OpenHandle,
    Bind,
    Unbind,
    CreateQueue,
    SetQueueMode,
    SetQueueMaxlen,
    Unknown
}

pub struct NFQError {
    reason: ErrorReason,
    description: String,
    cause: Option<Error>,
}

impl fmt::Debug for NFQError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let msg = format!("{:?}: {:?} (cause: {:?})",
                          self.reason, self.description, self.cause);
        formatter.write_str(msg.as_slice())
    }
}

impl fmt::Display for NFQError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let msg = format!("{:?} ({:?})", self.reason, self.description);
        formatter.write_str(msg.as_slice())
    }
}

impl Error for NFQError {
    fn description(&self) -> &str {
        self.description.as_slice()
    }
    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|c| &**c)
    }
}

impl<E: Error> From<E> for NFQError {
    fn from(err: E) -> NFQError {
        NFQError {
            reason: ErrorReason::Unknown,
            description: err.description().to_string(),
            cause: Some(err),
        }
    }
}

fn error(reason: ErrorReason, msg: &str, res: Option<c_int>) -> NFQError {
    let errno = unsafe { nfq_errno };
    let desc = match res {
        Some(r) => format!("{} (errno: {}, res: {})", msg, errno, r),
        None => format!("{}, (errno: {})", msg, errno)
    };
    NFQError {
        reason: reason,
        description: desc,
        cause: None,
    }
}

#[link(name="netfilter_queue")]
extern {
    static mut nfq_errno: c_int;
}

// NFQ Handle

#[repr(C)]
struct nfq_handle;

#[repr(C)]
pub enum ProtoFamily {
    INET = 2,
    INET6 = 10,
}

#[link(name="netfilter_queue")]
extern {
    fn nfq_open() -> *mut nfq_handle;
    fn nfq_close(handle: *mut nfq_handle) -> c_int;

    fn nfq_bind_pf(handle: *mut nfq_handle, pf: uint16_t) -> c_int;
    fn nfq_unbind_pf(handle: *mut nfq_handle, pf: uint16_t) -> c_int;
}

pub struct NFQHandle {
    ptr: *mut nfq_handle,
}

impl Drop for NFQHandle {
    fn drop(&mut self) {
        let ret = unsafe { nfq_close(self.ptr) };
        if ret != 0 {
            panic!("Failed to close nfq handle");
        }
    }
}

impl NFQHandle {
    pub fn new() -> Result<NFQHandle, NFQError> {
        let _g = NFQ_LOCK.lock().unwrap();

        let ptr = unsafe { nfq_open() };
        if ptr.is_null() {
            Err(error("Failed to allocate NFQHandle"))
        } else {
            Ok(NFQHandle{ ptr: ptr })
        }
    }

    pub fn bind(&mut self, proto: ProtoFamily) -> Result<(), NFQError> {
        let _g = NFQ_LOCK.lock().unwrap();

        let res = unsafe { nfq_bind_pf(self.ptr, proto as uint16_t) };
        if res < 0 {
            Err(error("Failed to bind packet filter"))
        } else {
            Ok(())
        }
    }

    pub fn unbind(&mut self, proto: ProtoFamily) -> Result<(), NFQError> {
        let _g = NFQ_LOCK.lock().unwrap();

        let res = unsafe { nfq_unbind_pf(self.ptr, proto as uint16_t) };
        if res < 0 {
            Err(error("Failed to unbind packet filter"))
        } else {
            Ok(())
        }
    }

}

// NFQ Queue
#[repr(C)]
struct nfq_q_handle;

#[repr(C)]
struct nfgenmsg;

#[repr(C)]
struct nfq_data;

pub struct NFGenMsg {
    ptr: *mut nfgenmsg
}
pub struct NFQData {
    ptr: *mut nfq_data
}

#[repr(C)]
struct CallbackData<A> {
    ctx: *mut A,
    func: fn(ctx: &mut A, msg: &NFGenMsg, ad: &NFQData) -> c_int
}

#[link(name="netfilter_queue")]
extern {
    fn nfq_create_queue(handle: *mut nfq_handle,
                        num: uint16_t,
                        cb: extern "C" fn(h: *mut nfq_q_handle,
                                          nfmsg: *mut nfgenmsg,
                                          nfad: *mut nfq_data,
                                          data: *mut c_void) -> c_int,
                        data: *mut c_void) -> *mut nfq_q_handle;
    fn nfq_destroy_queue(handle: *mut nfq_q_handle) -> c_int;
}

pub struct NFQQueue<A> {
    ptr: *mut nfq_q_handle,
    cb_data: CallbackData<A>,
    ctx: A
}

extern fn queue_callback<A>(h: *mut nfq_q_handle,
                            nfmsg: *mut nfgenmsg,
                            nfad: *mut nfq_data,
                            cdata: *mut c_void) -> c_int {
    let data: &CallbackData<A> = unsafe { mem::transmute(cdata) };
    let msg = NFGenMsg { ptr: nfmsg };
    let ad = NFQData { ptr: nfad };
    let mut ctx = match unsafe { data.ctx.as_mut() } {
        Some(c) => c,
        None => panic!("Could not deref ctx pointer")
    };
    (data.func)(ctx, &msg, &ad) as c_int
}

impl<A> NFQQueue<A> {
    pub fn new(h: &NFQHandle,
               num: u16,
               ctx: A,
               cb: fn(ctx: &mut A,
                      msg: &NFGenMsg,
                      ad: &NFQData) -> c_int
               ) -> Result<NFQQueue<A>, NFQError> {
        let _g = NFQ_LOCK.lock().unwrap();

        let fpointer: *const nfq_q_handle = null();
        let apointer: *const A = null();
        // So we initialise the queue obj as empty apart from the ctx
        // This is so we can take references to the mem inside
        let mut queue = NFQQueue {
            ctx: ctx,
            // Will be set after nfq_create_queue
            ptr: fpointer as *mut nfq_q_handle,
            cb_data: CallbackData{
                // Will be set to reference to queue.ctx
                ctx: apointer as *mut A,
                func: cb
            }
        };

        let ctxp: *mut A = &mut queue.ctx;
        queue.cb_data.ctx = ctxp;

        let ptr = unsafe { nfq_create_queue(h.ptr,
                                            num,
                                            queue_callback::<A>,
                                            mem::transmute(&queue.cb_data)) };
        if ptr.is_null() {
            Err(error("Failed to create queue"))
        } else {
            queue.ptr = ptr;
            Ok(queue)
        }
    }
}

impl<A> Drop for NFQQueue<A> {
    fn drop(&mut self) {
        let ret = unsafe { nfq_destroy_queue(self.ptr) };
        if ret != 0 {
            panic!("Failed to destroy nfq queue");
        }
    }
}
<commit_msg>Use new error handling infrastructure<commit_after>#![allow(non_camel_case_types)]

use libc::*;
use std::sync::{StaticMutex, MUTEX_INIT};
use std::error::Error;
use std::fmt;
use std::mem;
use std::ptr::null;

static NFQ_LOCK: StaticMutex = MUTEX_INIT;

#[derive(Debug)]
enum ErrorReason {
    OpenHandle,
    Bind,
    Unbind,
    CreateQueue,
    SetQueueMode,
    SetQueueMaxlen,
    Unknown
}

pub struct NFQError {
    reason: ErrorReason,
    description: String,
    cause: Option<Error>,
}

impl fmt::Debug for NFQError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let msg = format!("{:?}: {:?} (cause: {:?})",
                          self.reason, self.description, self.cause);
        formatter.write_str(msg.as_slice())
    }
}

impl fmt::Display for NFQError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let msg = format!("{:?} ({:?})", self.reason, self.description);
        formatter.write_str(msg.as_slice())
    }
}

impl Error for NFQError {
    fn description(&self) -> &str {
        self.description.as_slice()
    }
    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|c| &**c)
    }
}

impl<E: Error> From<E> for NFQError {
    fn from(err: E) -> NFQError {
        NFQError {
            reason: ErrorReason::Unknown,
            description: err.description().to_string(),
            cause: Some(err),
        }
    }
}

fn error(reason: ErrorReason, msg: &str, res: Option<c_int>) -> NFQError {
    let errno = unsafe { nfq_errno };
    let desc = match res {
        Some(r) => format!("{} (errno: {}, res: {})", msg, errno, r),
        None => format!("{}, (errno: {})", msg, errno)
    };
    NFQError {
        reason: reason,
        description: desc,
        cause: None,
    }
}

#[link(name="netfilter_queue")]
extern {
    static mut nfq_errno: c_int;
}

// NFQ Handle

#[repr(C)]
struct nfq_handle;

#[repr(C)]
pub enum ProtoFamily {
    INET = 2,
    INET6 = 10,
}

#[link(name="netfilter_queue")]
extern {
    fn nfq_open() -> *mut nfq_handle;
    fn nfq_close(handle: *mut nfq_handle) -> c_int;

    fn nfq_bind_pf(handle: *mut nfq_handle, pf: uint16_t) -> c_int;
    fn nfq_unbind_pf(handle: *mut nfq_handle, pf: uint16_t) -> c_int;
}

pub struct NFQHandle {
    ptr: *mut nfq_handle,
}

impl Drop for NFQHandle {
    fn drop(&mut self) {
        let ret = unsafe { nfq_close(self.ptr) };
        if ret != 0 {
            panic!("Failed to close nfq handle");
        }
    }
}

impl NFQHandle {
    pub fn new() -> Result<NFQHandle, NFQError> {
        let _g = NFQ_LOCK.lock().unwrap();

        let ptr = unsafe { nfq_open() };
        if ptr.is_null() {
            Err(error(ErrorReason::OpenHandle, "Failed to allocate NFQHandle", None))
        } else {
            Ok(NFQHandle{ ptr: ptr })
        }
    }

    pub fn bind(&mut self, proto: ProtoFamily) -> Result<(), NFQError> {
        let _g = NFQ_LOCK.lock().unwrap();

        let res = unsafe { nfq_bind_pf(self.ptr, proto as uint16_t) };
        if res < 0 {
            Err(error(ErrorReason::Bind, "Failed to bind packet filter", Some(res)))
        } else {
            Ok(())
        }
    }

    pub fn unbind(&mut self, proto: ProtoFamily) -> Result<(), NFQError> {
        let _g = NFQ_LOCK.lock().unwrap();

        let res = unsafe { nfq_unbind_pf(self.ptr, proto as uint16_t) };
        if res < 0 {
            Err(error(ErrorReason::Bind, "Failed to unbind packet filter", Some(res)))
        } else {
            Ok(())
        }
    }

}

// NFQ Queue
#[repr(C)]
struct nfq_q_handle;

#[repr(C)]
struct nfgenmsg;

#[repr(C)]
struct nfq_data;

pub struct NFGenMsg {
    ptr: *mut nfgenmsg
}
pub struct NFQData {
    ptr: *mut nfq_data
}

#[repr(C)]
struct CallbackData<A> {
    ctx: *mut A,
    func: fn(ctx: &mut A, msg: &NFGenMsg, ad: &NFQData) -> c_int
}

#[link(name="netfilter_queue")]
extern {
    fn nfq_create_queue(handle: *mut nfq_handle,
                        num: uint16_t,
                        cb: extern "C" fn(h: *mut nfq_q_handle,
                                          nfmsg: *mut nfgenmsg,
                                          nfad: *mut nfq_data,
                                          data: *mut c_void) -> c_int,
                        data: *mut c_void) -> *mut nfq_q_handle;
    fn nfq_destroy_queue(handle: *mut nfq_q_handle) -> c_int;
}

pub struct NFQQueue<A> {
    ptr: *mut nfq_q_handle,
    cb_data: CallbackData<A>,
    ctx: A
}

extern fn queue_callback<A>(h: *mut nfq_q_handle,
                            nfmsg: *mut nfgenmsg,
                            nfad: *mut nfq_data,
                            cdata: *mut c_void) -> c_int {
    let data: &CallbackData<A> = unsafe { mem::transmute(cdata) };
    let msg = NFGenMsg { ptr: nfmsg };
    let ad = NFQData { ptr: nfad };
    let mut ctx = match unsafe { data.ctx.as_mut() } {
        Some(c) => c,
        None => panic!("Could not deref ctx pointer")
    };
    (data.func)(ctx, &msg, &ad) as c_int
}

impl<A> NFQQueue<A> {
    pub fn new(h: &NFQHandle,
               num: u16,
               ctx: A,
               cb: fn(ctx: &mut A,
                      msg: &NFGenMsg,
                      ad: &NFQData) -> c_int
               ) -> Result<NFQQueue<A>, NFQError> {
        let _g = NFQ_LOCK.lock().unwrap();

        let fpointer: *const nfq_q_handle = null();
        let apointer: *const A = null();
        // So we initialise the queue obj as empty apart from the ctx
        // This is so we can take references to the mem inside
        let mut queue = NFQQueue {
            ctx: ctx,
            // Will be set after nfq_create_queue
            ptr: fpointer as *mut nfq_q_handle,
            cb_data: CallbackData{
                // Will be set to reference to queue.ctx
                ctx: apointer as *mut A,
                func: cb
            }
        };

        let ctxp: *mut A = &mut queue.ctx;
        queue.cb_data.ctx = ctxp;

        let ptr = unsafe { nfq_create_queue(h.ptr,
                                            num,
                                            queue_callback::<A>,
                                            mem::transmute(&queue.cb_data)) };
        if ptr.is_null() {
            Err(error("Failed to create queue"))
        } else {
            queue.ptr = ptr;
            Ok(queue)
        }
    }
}

impl<A> Drop for NFQQueue<A> {
    fn drop(&mut self) {
        let ret = unsafe { nfq_destroy_queue(self.ptr) };
        if ret != 0 {
            panic!("Failed to destroy nfq queue");
        }
    }
}
<|endoftext|>


<commit_before>use crate::{Error, Reference, Statuses};
use git2;
use std::path::{Path, PathBuf};

pub struct GitRepo {
    path: PathBuf,
    repo: git2::Repository,
}

unsafe impl Send for GitRepo {}

impl GitRepo {
    pub fn open<P>(path: P) -> Result<Self, Error>
    where
        P: Into<PathBuf>,
        P: AsRef<Path>,
    {
        let owned_path = path.into();
        let git_repo = git2::Repository::open(&owned_path)?;

        let repo = Self {
            path: owned_path,
            repo: git_repo,
        };

        Ok(repo)
    }

    pub fn path(&self) -> &Path {
        &self.path
    }

    pub fn statuses(&self) -> Result<Statuses<'_>, Error> {
        let mut opts = git2::StatusOptions::new();

        opts.include_ignored(false)
            .include_untracked(true)
            .recurse_untracked_dirs(true)
            .include_unreadable_as_untracked(true)
            .disable_pathspec_match(true)
            .exclude_submodules(true);

        self.repo
            .statuses(Some(&mut opts))
            .map(|x| x.into())
            .map_err(|x| x.into())
    }

    pub fn reset(&self) -> Result<Reference, Error> {
        let head = self.repo.head()?;
        let obj = head.peel(git2::ObjectType::Any)?;

        self.repo.reset(&obj, git2::ResetType::Hard, None)?;

        Reference::from_ref(&head)
    }

    pub fn checkout(&self, branch_name: &str) -> Result<bool, Error> {
        let branch_type = self.get_branch_type(branch_name)?;
        let branch = self.repo.find_branch(branch_name, branch_type)?;
        let obj = branch.get().peel(git2::ObjectType::Commit)?;

        match branch_type {
            git2::BranchType::Local => self.checkout_local(branch_name, &obj),
            git2::BranchType::Remote => self.checkout_remote(&obj),
        }
    }

    pub fn delete_local_branch(&self, branch_name: &str) -> Result<(), Error> {
        self.repo
            .find_branch(branch_name, git2::BranchType::Local)?
            .delete()?;

        Ok(())
    }

    pub fn fetch(&self) -> Result<(), Error> {
        let mut options = {
            let mut remote_callbacks = git2::RemoteCallbacks::new();
            remote_callbacks.credentials(
                |_s: &str,
                 _os: Option<&str>,
                 _ct: git2::CredentialType|
                 -> Result<git2::Cred, git2::Error> { git2::Cred::default() },
            );

            let mut o = git2::FetchOptions::new();
            o.remote_callbacks(remote_callbacks);
            o
        };

        let refspecs = self.repo.find_remote("origin")?.fetch_refspecs()?;
        let refspec_collection = refspecs.iter().filter_map(|x| x).collect::<Vec<_>>();

        if let Err(e) =
            self.repo
                .find_remote("origin")?
                .fetch(&refspec_collection, Some(&mut options), None)
        {
            let asd = format!("{:?}", e);
            return Err(Error::GenericError);
        }

        Ok(())
    }

    pub fn has_local_branch(&self, branch_name: &str) -> Result<(), Error> {
        self.repo
            .find_branch(branch_name, git2::BranchType::Local)?;

        Ok(())
    }

    fn get_branch_type(&self, branch_name: &str) -> Result<git2::BranchType, Error> {
        let components = branch_name.split('/').collect::<Vec<_>>();

        match components.len() {
            0 => Err(Error::ZeroSizedBranchName),
            1 => Ok(git2::BranchType::Local),
            _ => {
                if self.repo.find_remote(&components[0]).is_ok() {
                    Ok(git2::BranchType::Remote)
                } else {
                    Ok(git2::BranchType::Local)
                }
            }
        }
    }

    fn checkout_local(&self, branch_name: &str, obj: &git2::Object<'_>) -> Result<bool, Error> {
        self.repo.checkout_tree(obj, None)?;

        let branch_str = format!("refs/heads/{}", branch_name);
        let branch_ref = self.repo.find_reference(&branch_str)?;

        self.repo
            .set_head(branch_ref.name().ok_or(Error::GenericError)?)?;

        Ok(true)
    }

    fn checkout_remote(&self, obj: &git2::Object<'_>) -> Result<bool, Error> {
        let head_id = self.repo.head()?.peel(git2::ObjectType::Any)?.id();

        if head_id == obj.id() {
            return Ok(false);
        }

        self.repo.set_head_detached(obj.id())?;
        self.repo.reset(obj, git2::ResetType::Hard, None)?;

        Ok(true)
    }
}
<commit_msg>Tweaking fetch. Still broken<commit_after>use crate::{Error, Reference, Statuses};
use git2;
use std::path::{Path, PathBuf};

pub struct GitRepo {
    path: PathBuf,
    repo: git2::Repository,
}

unsafe impl Send for GitRepo {}

impl GitRepo {
    pub fn open<P>(path: P) -> Result<Self, Error>
    where
        P: Into<PathBuf>,
        P: AsRef<Path>,
    {
        let owned_path = path.into();
        let git_repo = git2::Repository::open(&owned_path)?;

        let repo = Self {
            path: owned_path,
            repo: git_repo,
        };

        Ok(repo)
    }

    pub fn path(&self) -> &Path {
        &self.path
    }

    pub fn statuses(&self) -> Result<Statuses<'_>, Error> {
        let mut opts = git2::StatusOptions::new();

        opts.include_ignored(false)
            .include_untracked(true)
            .recurse_untracked_dirs(true)
            .include_unreadable_as_untracked(true)
            .disable_pathspec_match(true)
            .exclude_submodules(true);

        self.repo
            .statuses(Some(&mut opts))
            .map(|x| x.into())
            .map_err(|x| x.into())
    }

    pub fn reset(&self) -> Result<Reference, Error> {
        let head = self.repo.head()?;
        let obj = head.peel(git2::ObjectType::Any)?;

        self.repo.reset(&obj, git2::ResetType::Hard, None)?;

        Reference::from_ref(&head)
    }

    pub fn checkout(&self, branch_name: &str) -> Result<bool, Error> {
        let branch_type = self.get_branch_type(branch_name)?;
        let branch = self.repo.find_branch(branch_name, branch_type)?;
        let obj = branch.get().peel(git2::ObjectType::Commit)?;

        match branch_type {
            git2::BranchType::Local => self.checkout_local(branch_name, &obj),
            git2::BranchType::Remote => self.checkout_remote(&obj),
        }
    }

    pub fn delete_local_branch(&self, branch_name: &str) -> Result<(), Error> {
        self.repo
            .find_branch(branch_name, git2::BranchType::Local)?
            .delete()?;

        Ok(())
    }

    pub fn fetch(&self) -> Result<(), Error> {
        let refspecs = self.repo.find_remote("origin")?.fetch_refspecs()?;
        let refspec_collection = refspecs.iter().filter_map(|x| x).collect::<Vec<_>>();

        let mut fetch_options = {
            let mut remote_callbacks = git2::RemoteCallbacks::new();
            remote_callbacks.credentials(Self::credentials_callback);

            let mut o = git2::FetchOptions::new();
            o.remote_callbacks(remote_callbacks);
            o
        };

        // TODO: Instead of refspec_collection, maybe the following:
        // &["refs/heads/*:refs/heads/*"]
        // Example here: https://github.com/rust-lang/crates.io/blob/master/src/git.rs#L114-L209

        if let Err(e) =
            self.repo
                .find_remote("origin")?
                .fetch(&refspec_collection, Some(&mut fetch_options), None)
        {
            let asd = format!("{:?}", e);
            return Err(Error::GenericError);
        }

        Ok(())
    }

    pub fn has_local_branch(&self, branch_name: &str) -> Result<(), Error> {
        self.repo
            .find_branch(branch_name, git2::BranchType::Local)?;

        Ok(())
    }

    fn get_branch_type(&self, branch_name: &str) -> Result<git2::BranchType, Error> {
        let components = branch_name.split('/').collect::<Vec<_>>();

        match components.len() {
            0 => Err(Error::ZeroSizedBranchName),
            1 => Ok(git2::BranchType::Local),
            _ => {
                if self.repo.find_remote(&components[0]).is_ok() {
                    Ok(git2::BranchType::Remote)
                } else {
                    Ok(git2::BranchType::Local)
                }
            }
        }
    }

    fn checkout_local(&self, branch_name: &str, obj: &git2::Object<'_>) -> Result<bool, Error> {
        self.repo.checkout_tree(obj, None)?;

        let branch_str = format!("refs/heads/{}", branch_name);
        let branch_ref = self.repo.find_reference(&branch_str)?;

        self.repo
            .set_head(branch_ref.name().ok_or(Error::GenericError)?)?;

        Ok(true)
    }

    fn checkout_remote(&self, obj: &git2::Object<'_>) -> Result<bool, Error> {
        let head_id = self.repo.head()?.peel(git2::ObjectType::Any)?.id();

        if head_id == obj.id() {
            return Ok(false);
        }

        self.repo.set_head_detached(obj.id())?;
        self.repo.reset(obj, git2::ResetType::Hard, None)?;

        Ok(true)
    }

    fn credentials_callback(
        _user: &str,
        _user_from_url: Option<&str>,
        _cred: git2::CredentialType,
    ) -> Result<git2::Cred, git2::Error> {
        git2::Cred::ssh_key_from_agent("kgretchev")
    }
}
<|endoftext|>


<commit_before>//! The functions in this section provide optimized copying to persistent memory
//!
//! The `copy`, `copy_nonoverlapping`, and `write_bytes`, provide the same memory copying as
//! `memmove(3)`, `memcpy(3)`, and `memset(3)`, and ensure that the result has been flushed to persistence before returning.
//!
//! > **Warning:** Using these functions where `is_pmem(1)` returns false may not do anything useful.
//! >              Use the normal libc functions in that case.

use ::std::mem;
use ::std::io;
use ::std::marker::PhantomData;

use ::libc::{c_void, c_int};
use ::libc::size_t;
use ::pmem_sys as ffi;

use pmap::PersistentMap;

/// Persistent memory virtual pointer
///
/// This pointer is safe to store.
#[derive(Copy, Clone)]
pub struct PmemConstVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemConstVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemConstVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemConstVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(&self) -> PmemConstVirtualPtr<U> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }

    pub unsafe fn as_mut(&self) -> PmemMutVirtualPtr<T> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> PmemConstVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemConstVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemConstVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(&self, pool: &PersistentMap) -> PmemConstPtr<T> {
        let new_virt = PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: self._t };
        PmemConstPtr { virt: new_virt, pool: pool.as_ptr() }
    }
}

impl<T> ::std::fmt::Pointer for PmemConstVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:#x}:{:#x}",self.poolid, self.offset)
    }
}

impl<T> ::std::fmt::Debug for PmemConstVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "PmemVirt *const {{ pool: {:#x}, offset: {:#x} }}", self.poolid, self.offset)
    }
}

/// Persistent memory virtual mutable pointer
///
/// This pointer is safe to store.
#[derive(Copy, Clone)]
pub struct PmemMutVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemMutVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemMutVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemMutVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(&self) -> PmemMutVirtualPtr<U> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }

    pub unsafe fn as_const(&self) -> PmemConstVirtualPtr<T> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> ::std::fmt::Pointer for PmemMutVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:#x}:{:#x}",self.poolid, self.offset)
    }
}

impl<T> ::std::fmt::Debug for PmemMutVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "PmemVirt *mut {{ pool: {:#x}, offset: {:#x} }}", self.poolid, self.offset)
    }
}

impl<T> PmemMutVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemMutVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemMutVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(&self, pool: &mut PersistentMap) -> PmemMutPtr<T> {
        let new_virt = PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: self._t };
        PmemMutPtr { virt: new_virt, pool: pool.as_mut_ptr() }
    }
}

/// Direct `*const T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
#[derive(Copy, Clone)]
pub struct PmemConstPtr<T: ?Sized> {
    virt: PmemConstVirtualPtr<T>,
    pool: *const T,
}

impl<T: ?Sized> PmemConstPtr<T> {
    pub fn is_null(&self) -> bool { self.virt.is_null() }

    pub unsafe fn as_mut(&self) -> PmemMutPtr<T> {
        PmemMutPtr { virt: self.virt.as_mut(), pool: self.pool as *mut T }
    }
}

impl<T> PmemConstPtr<T> {
    pub unsafe fn direct(&self) -> *const T {
        if self.is_null() {
            ::std::ptr::null()
        } else {
            self.pool.offset(self.virt.offset as isize) as *const T
        }
    }

    pub fn as_virtual(self) -> PmemConstVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemConstPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(&self) -> PmemConstPtr<U> {
        let new_virt = self.virt.as_type();
        PmemConstPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

impl<T> ::std::fmt::Pointer for PmemConstPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:p} -> {:p}",self.virt, unsafe { self.direct() })
    }
}

impl<T> ::std::fmt::Debug for PmemConstPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "Pmem *const {{ pool: {:#x}, offset: {:#x} }}", self.virt.poolid, self.virt.offset)
    }
}

/// Direct `*mut T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
#[derive(Copy, Clone)]
pub struct PmemMutPtr<T: ?Sized> {
    virt: PmemMutVirtualPtr<T>,
    pool: *mut T,
}

impl<T: ?Sized> PmemMutPtr<T> {
    pub fn is_null(&self) -> bool { self.virt.is_null() }

    pub unsafe fn as_const(&self) -> PmemConstPtr<T> {
        PmemConstPtr { virt: self.virt.as_const(), pool: self.pool as *const T }
    }
}

impl<T> PmemMutPtr<T> {
    pub unsafe fn direct(&self) -> *mut T {
        if self.is_null() {
            ::std::ptr::null_mut()
        } else {
            self.pool.offset(self.virt.offset as isize) as *mut T
        }
    }

    pub fn as_virtual(self) -> PmemMutVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemMutPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(&self) -> PmemMutPtr<U> {
        let new_virt = self.virt.as_type();
        PmemMutPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

impl<T> ::std::fmt::Pointer for PmemMutPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:p} -> {:p}",self.virt, unsafe { self.direct() })
    }
}

impl<T> ::std::fmt::Debug for PmemMutPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "Pmem *mut {{ pool: {:#x}, offset: {:#x} }}", self.virt.poolid, self.virt.offset)
    }
}

pub fn null<T>() -> PmemConstVirtualPtr<T> {
    PmemConstVirtualPtr::null()
}

pub fn null_mut<T>() -> PmemMutVirtualPtr<T> {
    PmemMutVirtualPtr::null()
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may overlap.
///
/// `copy` is semantically equivalent to C's `memmove` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Care must be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memmove_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may _not_ overlap.
///
/// `copy_nonoverlapping` is semantically equivalent to C's `memcpy` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Beyond requiring that the program must be allowed to access both regions of memory,
/// it is _Undefined Behavior_ for source and destination to overlap.
/// Care must also be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy_nonoverlapping<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memcpy_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Invokes memset on the specified pointer, setting `count * size_of::<T>()` bytes of memory starting at `pmemdest` to `val`.
///
/// Ensures that the result has been flushed to persistence before returning.
pub unsafe fn write_bytes<T>(pmemdest: *mut T, val: u8, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memset_persist(pmemdest as *mut c_void, val as c_int, len as size_t);
}

/// Overwrites a memory location with the given value without reading or dropping the old value.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// This operation is marked unsafe because it accepts a raw pointer.
///
/// It does not drop the contents of dst. This is safe, but it could leak allocations or resources,
/// so care must be taken not to overwrite an object that should be dropped.
///
/// This is appropriate for initializing uninitialized memory, or overwriting memory that has previously been read from.
pub unsafe fn write<T>(pmemdest: *mut T, val: T) { copy_nonoverlapping(&val as *const _, pmemdest, 1) }

pub unsafe fn msync<T>(pmemdest: *const T, count: usize) -> Result<(), io::Error> {
    let len = count * mem::size_of::<T>();
    let r = ffi::pmem_msync(pmemdest as *const c_void, len as size_t);
    if r == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}
<commit_msg>feat: xxx<commit_after>//! The functions in this section provide optimized copying to persistent memory
//!
//! The `copy`, `copy_nonoverlapping`, and `write_bytes`, provide the same memory copying as
//! `memmove(3)`, `memcpy(3)`, and `memset(3)`, and ensure that the result has been flushed to persistence before returning.
//!
//! > **Warning:** Using these functions where `is_pmem(1)` returns false may not do anything useful.
//! >              Use the normal libc functions in that case.

use ::std::mem;
use ::std::io;
use ::std::marker::PhantomData;

use ::libc::{c_void, c_int};
use ::libc::size_t;
use ::pmem_sys as ffi;

use pmap::PersistentMap;

/// Persistent memory virtual pointer
///
/// This pointer is safe to store.
#[derive(Copy, Clone)]
pub struct PmemConstVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemConstVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemConstVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemConstVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(&self) -> PmemConstVirtualPtr<U> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }

    pub unsafe fn as_mut(&self) -> PmemMutVirtualPtr<T> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> PmemConstVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemConstVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemConstVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(&self, pool: &PersistentMap) -> PmemConstPtr<T> {
        let new_virt = PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: self._t };
        PmemConstPtr { virt: new_virt, pool: pool.as_ptr() }
    }
}

impl<T> ::std::fmt::Pointer for PmemConstVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:#x}:{:#x}",self.poolid, self.offset)
    }
}

impl<T> ::std::fmt::Debug for PmemConstVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        if self.is_null() {
            write!(f, "PmemVirt *const NULL")
        } else {
            write!(f, "PmemVirt *const {{ pool: {:#x}, offset: {:#x} }}", self.poolid, self.offset)
        }
    }
}

/// Persistent memory virtual mutable pointer
///
/// This pointer is safe to store.
#[derive(Copy, Clone)]
pub struct PmemMutVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemMutVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemMutVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemMutVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(&self) -> PmemMutVirtualPtr<U> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }

    pub unsafe fn as_const(&self) -> PmemConstVirtualPtr<T> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> ::std::fmt::Pointer for PmemMutVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:#x}:{:#x}",self.poolid, self.offset)
    }
}

impl<T> ::std::fmt::Debug for PmemMutVirtualPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        if self.is_null() {
            write!(f, "PmemVirt *mut NULL")
        } else {
            write!(f, "PmemVirt *mut {{ pool: {:#x}, offset: {:#x} }}", self.poolid, self.offset)
        }
    }
}

impl<T> PmemMutVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemMutVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemMutVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(&self, pool: &mut PersistentMap) -> PmemMutPtr<T> {
        let new_virt = PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: self._t };
        PmemMutPtr { virt: new_virt, pool: pool.as_mut_ptr() }
    }
}

/// Direct `*const T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
#[derive(Copy, Clone)]
pub struct PmemConstPtr<T: ?Sized> {
    virt: PmemConstVirtualPtr<T>,
    pool: *const T,
}

impl<T: ?Sized> PmemConstPtr<T> {
    pub fn is_null(&self) -> bool { self.virt.is_null() }

    pub unsafe fn as_mut(&self) -> PmemMutPtr<T> {
        PmemMutPtr { virt: self.virt.as_mut(), pool: self.pool as *mut T }
    }
}

impl<T> PmemConstPtr<T> {
    pub unsafe fn direct(&self) -> *const T {
        if self.is_null() {
            ::std::ptr::null()
        } else {
            self.pool.offset(self.virt.offset as isize) as *const T
        }
    }

    pub fn as_virtual(self) -> PmemConstVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemConstPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(&self) -> PmemConstPtr<U> {
        let new_virt = self.virt.as_type();
        PmemConstPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

impl<T> ::std::fmt::Pointer for PmemConstPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:p} -> {:p}",self.virt, unsafe { self.direct() })
    }
}

impl<T> ::std::fmt::Debug for PmemConstPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        if self.is_null() {
            write!(f, "Pmem *const NULL")
        } else {
            write!(f, "Pmem *const {{ pool: {:#x}, offset: {:#x} }}", self.virt.poolid, self.virt.offset)
        }
    }
}

/// Direct `*mut T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
#[derive(Copy, Clone)]
pub struct PmemMutPtr<T: ?Sized> {
    virt: PmemMutVirtualPtr<T>,
    pool: *mut T,
}

impl<T: ?Sized> PmemMutPtr<T> {
    pub fn is_null(&self) -> bool { self.virt.is_null() }

    pub unsafe fn as_const(&self) -> PmemConstPtr<T> {
        PmemConstPtr { virt: self.virt.as_const(), pool: self.pool as *const T }
    }
}

impl<T> PmemMutPtr<T> {
    pub unsafe fn direct(&self) -> *mut T {
        if self.is_null() {
            ::std::ptr::null_mut()
        } else {
            self.pool.offset(self.virt.offset as isize) as *mut T
        }
    }

    pub fn as_virtual(self) -> PmemMutVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemMutPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(&self) -> PmemMutPtr<U> {
        let new_virt = self.virt.as_type();
        PmemMutPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

impl<T> ::std::fmt::Pointer for PmemMutPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:p} -> {:p}",self.virt, unsafe { self.direct() })
    }
}

impl<T> ::std::fmt::Debug for PmemMutPtr<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        if self.is_null() {
            write!(f, "Pmem *mut NULL")
        } else {
            write!(f, "Pmem *mut {{ pool: {:#x}, offset: {:#x} }}", self.virt.poolid, self.virt.offset)
        }
    }
}

pub fn null<T>() -> PmemConstVirtualPtr<T> {
    PmemConstVirtualPtr::null()
}

pub fn null_mut<T>() -> PmemMutVirtualPtr<T> {
    PmemMutVirtualPtr::null()
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may overlap.
///
/// `copy` is semantically equivalent to C's `memmove` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Care must be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memmove_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may _not_ overlap.
///
/// `copy_nonoverlapping` is semantically equivalent to C's `memcpy` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Beyond requiring that the program must be allowed to access both regions of memory,
/// it is _Undefined Behavior_ for source and destination to overlap.
/// Care must also be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy_nonoverlapping<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memcpy_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Invokes memset on the specified pointer, setting `count * size_of::<T>()` bytes of memory starting at `pmemdest` to `val`.
///
/// Ensures that the result has been flushed to persistence before returning.
pub unsafe fn write_bytes<T>(pmemdest: *mut T, val: u8, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memset_persist(pmemdest as *mut c_void, val as c_int, len as size_t);
}

/// Overwrites a memory location with the given value without reading or dropping the old value.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// This operation is marked unsafe because it accepts a raw pointer.
///
/// It does not drop the contents of dst. This is safe, but it could leak allocations or resources,
/// so care must be taken not to overwrite an object that should be dropped.
///
/// This is appropriate for initializing uninitialized memory, or overwriting memory that has previously been read from.
pub unsafe fn write<T>(pmemdest: *mut T, val: T) { copy_nonoverlapping(&val as *const _, pmemdest, 1) }

pub unsafe fn msync<T>(pmemdest: *const T, count: usize) -> Result<(), io::Error> {
    let len = count * mem::size_of::<T>();
    let r = ffi::pmem_msync(pmemdest as *const c_void, len as size_t);
    if r == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}
<|endoftext|>