<commit_before>use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
use tools;

const TEMPLATE: &'static str = "
{bin} {version}
{about}

USAGE:
    {usage}

SUBCOMMANDS:
{subcommands}

OPTIONS:
{unified}";

const ABOUT: &'static str = "
gfxtools is a collection of tools for working with various gene annotation
file formats. Submit bug reports, feature requests, or view the source code
at https://github.com/bow/gfxtools.";

const TEMPLATE_SUBCMD: &'static str = "
USAGE:
    {usage}

ARGS:
{positionals}

OPTIONS:
{unified}";

/// Constructs a new `clap::App` for argument parsing.
pub fn build_cli() -> App<'static, 'static> {
    App::new("gfxtools")
        .version(crate_version!())
        .author(crate_authors!())
        .about(ABOUT)
        .template(TEMPLATE)
        .max_term_width(80)
        .settings(&[
            AppSettings::GlobalVersion,
            AppSettings::SubcommandRequiredElseHelp,
            AppSettings::DisableHelpSubcommand,
            AppSettings::VersionlessSubcommands])
        .subcommand(
            SubCommand::with_name("stats")
                .about("Gathers various statistics")
                .template(TEMPLATE_SUBCMD)
                .arg(Arg::with_name("input")
                        .value_name("input")
                        .help("Path to input annotation file or '-' for stdin")
                        .takes_value(true)
                        .required(true)))
        .subcommand(
            SubCommand::with_name("gtf2refflat")
                .about("Converts from the GTF format to refFlat")
                .template(TEMPLATE_SUBCMD)
                .arg(Arg::with_name("input")
                        .value_name("input")
                        .help("Path to input annotation file or '-' for stdin")
                        .takes_value(true)
                        .required(true))
                .arg(Arg::with_name("output")
                        .value_name("output")
                        .help("Path to output annotation file or '-' for stdout")
                        .takes_value(true)
                        .required(true)))
}

/// Runs the appropriate tool given the subcommand argument matches.
pub fn run(matches: ArgMatches) -> Result<(), &'static str> {
    match matches.subcommand() {
        ("stats", Some(m)) =>       tools::stats::run(m),
        ("gtf2refflat", Some(m)) => tools::convert_gtf2refflat::run(m),
        // We should not reach this point since we already require
        // that subcommands must be present in the app settings.
        _   => Err("Unexpected subcommand parsing error")
    }
}
<commit_msg>Update formatting with rustfmt<commit_after>use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
use tools;

const TEMPLATE: &'static str = "
{bin} {version}
{about}

USAGE:
    {usage}

SUBCOMMANDS:
{subcommands}

OPTIONS:
{unified}";

const ABOUT: &'static str = "
gfxtools is a collection of tools for working with various gene annotation
file formats. Submit bug reports, feature requests, or view the source code
at https://github.com/bow/gfxtools.";

const TEMPLATE_SUBCMD: &'static str = "
USAGE:
    {usage}

ARGS:
{positionals}

OPTIONS:
{unified}";

/// Constructs a new `clap::App` for argument parsing.
pub fn build_cli() -> App<'static, 'static> {
    App::new("gfxtools")
        .version(crate_version!())
        .author(crate_authors!())
        .about(ABOUT)
        .template(TEMPLATE)
        .max_term_width(80)
        .settings(&[AppSettings::GlobalVersion,
                    AppSettings::SubcommandRequiredElseHelp,
                    AppSettings::DisableHelpSubcommand,
                    AppSettings::VersionlessSubcommands])
        .subcommand(SubCommand::with_name("stats")
                        .about("Gathers various statistics")
                        .template(TEMPLATE_SUBCMD)
                        .arg(Arg::with_name("input")
                                 .value_name("input")
                                 .help("Path to input annotation file or '-' for stdin")
                                 .takes_value(true)
                                 .required(true)))
        .subcommand(SubCommand::with_name("gtf2refflat")
                        .about("Converts from the GTF format to refFlat")
                        .template(TEMPLATE_SUBCMD)
                        .arg(Arg::with_name("input")
                                 .value_name("input")
                                 .help("Path to input annotation file or '-' for stdin")
                                 .takes_value(true)
                                 .required(true))
                        .arg(Arg::with_name("output")
                                 .value_name("output")
                                 .help("Path to output annotation file or '-' for stdout")
                                 .takes_value(true)
                                 .required(true)))
}

/// Runs the appropriate tool given the subcommand argument matches.
pub fn run(matches: ArgMatches) -> Result<(), &'static str> {
    match matches.subcommand() {
        ("stats", Some(m)) => tools::stats::run(m),
        ("gtf2refflat", Some(m)) => tools::convert_gtf2refflat::run(m),
        // We should not reach this point since we already require
        // that subcommands must be present in the app settings.
        _ => Err("Unexpected subcommand parsing error"),
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Jason Lingle
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Miscelaneous things used to integrate other code with Supercow, but which
//! are not of interest to end users.

use std::borrow::Borrow;
use std::ffi::{CStr, OsStr};
use std::mem;
use std::path::Path;
use std::ptr;
use std::rc::Rc;
use std::slice;
use std::sync::Arc;

/// Marker trait indicating a `Deref`-like which always returns the same
/// reference.
///
/// This is not indended for general use outside Supercow. Notably, `Box` and
/// mundane references satisfy this trait's requirements, but deliberately do
/// not implement it. It is also not a subtrait of `Deref` due to some
/// additional special logic around boxes.
///
/// ## Unsafety
///
/// Behaviour is undefined if the implementation does not always return the
/// same reference from `deref()` for any particular implementing value
/// (including if that value is moved).
pub unsafe trait ConstDeref {
    /// The type this value dereferences to.
    type Target : ?Sized;
    /// Returns the (constant) value that this value dereferences to.
    fn const_deref(&self) -> &Self::Target;
}

unsafe impl<T : ?Sized> ConstDeref for Rc<T> {
    type Target = T;
    fn const_deref(&self) -> &T { self }
}

unsafe impl<T : ?Sized> ConstDeref for Arc<T> {
    type Target = T;
    fn const_deref(&self) -> &T { self }
}

unsafe impl<T : ConstDeref + ?Sized> ConstDeref for Box<T> {
    type Target = T::Target;
    fn const_deref(&self) -> &T::Target {
        (**self).const_deref()
    }
}

/// The maximum displacement (relative to the start of the object) that a
/// reference pointing into `self` from an instance of `SafeBorrow` may have.
///
/// This value is deliberately conservative to account for other memory layout
/// factors.
pub const MAX_INTERNAL_BORROW_DISPLACEMENT: usize = 2048;

/// Extension of `Borrow` used to allow `Supercow::to_mut()` to work safely.
///
/// ## Unsafety
///
/// Behaviour is undefined if the `borrow()` implementation may return a
/// reference into `self` which is more than `MAX_INTERNAL_BORROW_DISPLACEMENT`
/// bytes beyond the base of `self`.
pub unsafe trait SafeBorrow<T : ?Sized>: Borrow<T> {
    /// Given `ptr`, which was obtained from a prior call to `Self::borrow()`,
    /// return a value with the same nominal lifetime which is guaranteed to
    /// survive mutations to `Self`.
    ///
    /// Types which implement `Borrow` by pure, constant pointer arithmetic on
    /// `self` can simply return `ptr` unmodified. Other types typically need
    /// to provide some static reference, such as the empty string for `&str`.
    ///
    /// ## Unsafety
    ///
    /// Behaviour is undefined if this call returns `ptr`, but a mutation to
    /// `Self` could invalidate the reference.
    fn borrow_replacement<'a>(ptr: &'a T) -> &'a T;
}
unsafe impl<T : ?Sized> SafeBorrow<T> for T {
    fn borrow_replacement(ptr: &T) -> &T { ptr }
}
unsafe impl<B, T> SafeBorrow<[B]> for T where T : Borrow<[B]> {
    fn borrow_replacement(_: &[B]) -> &[B] {
        unsafe {
            slice::from_raw_parts(1 as usize as *const B, 0)
        }
    }
}
unsafe impl<T> SafeBorrow<str> for T where T : Borrow<str> {
    fn borrow_replacement(_: &str) -> &str { "" }
}
unsafe impl<T> SafeBorrow<CStr> for T
    where T : Borrow<CStr> {
        fn borrow_replacement(_: &CStr) -> &CStr {
        static EMPTY_CSTR: &'static [u8] = &[0];
        unsafe {
            CStr::from_bytes_with_nul_unchecked(EMPTY_CSTR)
        }
    }
    }
unsafe impl<T> SafeBorrow<OsStr> for T
    where T : Borrow<OsStr> {
            fn borrow_replacement(_: &OsStr) -> &OsStr {
                OsStr::new("")
            }
        }
unsafe impl<T> SafeBorrow<Path> for T
    where T : Borrow<Path> {
                fn borrow_replacement(_: &Path) -> &Path {
                Path::new("")
            }
            }

/// Marker trait identifying a reference type which begins with an absolute
/// address and contains no other address-dependent information.
///
/// `Supercow` expects to be able to read the first pointer-sized value of such
/// a reference and perform address arithmetic upon it.
///
/// There is no utility of applying this trait to anything other than a const
/// reference.
///
/// ## Unsafety
///
/// Behaviour is undefined if a marked type does not begin with a real pointer
/// to a value (with the usual exception of ZSTs, where the pointer does not
/// need to point to anything in particular) or if other parts of the type
/// contain address-dependent information.
///
/// Behaviour is undefined if the reference has any `Drop` implementation,
/// should a future Rust version make such things possible.
pub unsafe trait PointerFirstRef { }
unsafe impl<'a, T : Sized> PointerFirstRef for &'a T { }
unsafe impl<'a, T> PointerFirstRef for &'a [T] { }
unsafe impl<'a> PointerFirstRef for &'a str { }
unsafe impl<'a> PointerFirstRef for &'a ::std::ffi::CStr { }
unsafe impl<'a> PointerFirstRef for &'a ::std::ffi::OsStr { }
unsafe impl<'a> PointerFirstRef for &'a ::std::path::Path { }

/// Like `std::convert::From`, but without the blanket implementations that
/// cause problems for `supercow_features!`.
pub trait SharedFrom<T> {
    /// Converts the given `T` to `Self`.
    fn shared_from(t: T) -> Self;
}
impl <T> SharedFrom<Rc<T>> for Rc<T> {
    fn shared_from(t: Rc<T>) -> Rc<T> { t }
}
impl <T> SharedFrom<Arc<T>> for Arc<T> {
    fn shared_from(t: Arc<T>) -> Arc<T> { t }
}

/// Describes how an `OWNED` or `SHARED` value is stored in a `Supercow`.
///
/// All notes for `*_b` functions are the same as the corresponding `*_a`
/// functions.
///
/// ## Unsafety
///
/// `Supercow` relies strongly on the contracts of the functions in this trait
/// being implemented correctly.
pub unsafe trait OwnedStorage<A, B> : Default {
    /// Allocates the given owned value.
    ///
    /// `self` is a `Default`-initialised instance.
    ///
    /// Returns a pointer with 2-byte alignment.
    ///
    /// ## Unsafety
    ///
    /// Behaviour is undefined if this call returns a pointer with incorrect
    /// alignment.
    ///
    /// Behaviour is undefined if the returned value is an address inside
    /// `self` offset by more than `MAX_INTERNAL_BORROW_DISPLACEMENT/2` (note
    /// division by two).
    ///
    /// Behaviour is undefined if this returns a null pointer. (But the
    /// returned pointer does not need to actually point at anything.)
    fn allocate_a(&mut self, value: A) -> *mut ();
    /// See `allocate_a`.
    fn allocate_b(&mut self, value: B) -> *mut ();
    /// Extracts the immutable reference from the saved pointer and storage.
    ///
    /// ## Unsafety
    ///
    /// This call may assume that `ptr` is exactly a (2-byte-aligned) value it
    /// returned from `allocate_a`, and that `self` was initialised by a call
    /// to `allocate_a`.
    unsafe fn get_ptr_a<'a>(&'a self, ptr: *mut ()) -> &'a A;
    /// See `get_ptr_a`.
    unsafe fn get_ptr_b<'a>(&'a self, ptr: *mut ()) -> &'a B;
    /// Extracts the mutable reference from the saved pointer and storage.
    ///
    /// ## Unsafety
    ///
    /// This call may assume that `ptr` is exactly a (2-byte-aligned) value it
    /// returned from `allocate_a` and that `self` was initialised by a call to
    /// `allocate_a`.
    unsafe fn get_mut_a<'a>(&'a mut self, ptr: *mut ()) -> &'a mut A;
    /// See `get_mut_a`.
    unsafe fn get_mut_b<'a>(&'a mut self, ptr: *mut ()) -> &'a mut B;
    /// Releases any allocations that would not be released by `Stored`
    /// being dropped.
    ///
    /// ## Unsafety
    ///
    /// This call may assume that `ptr` is exactly a (2-byte-aligned) value it
    /// returned from `allocate_a`.
    ///
    /// Once this function is called, the given `ptr` is considered invalid and
    /// any further use is undefined.
    unsafe fn deallocate_a(&mut self, ptr: *mut ());
    /// See `deallocate_b`.
    unsafe fn deallocate_b(&mut self, ptr: *mut ());
    /// Like `deallocate_a()`, but also return the owned value.
    unsafe fn deallocate_into_a(&mut self, ptr: *mut ()) -> A;
    /// See `deallocate_into_a`.
    unsafe fn deallocate_into_b(&mut self, ptr: *mut ()) -> B;

    /// Returns whether this storage implementation ever causes the owned
    /// object to be stored internally to the `Supercow`.
    ///
    /// ## Unsafety
    ///
    /// Behaviour is undefined if this returns `false` but the owned value is
    /// stored within the `Supercow`.
    fn is_internal_storage() -> bool;
}

/// Causes the `OWNED` or `SHARED` value of a `Supercow` to be stored inline.
///
/// This makes allocation of owned `Supercow`s much faster, at the expense of
/// making the `Supercow` itself much bigger (since it now must contain the
/// whole object).
#[derive(Clone, Copy, Debug)]
pub struct InlineStorage<A, B>(InlineStorageImpl<A, B>);

#[derive(Clone, Copy, Debug)]
enum InlineStorageImpl<A, B> {
    None,
    A(A),
    B(B),
}

impl<A, B> Default for InlineStorage<A, B> {
    fn default() -> Self {
        InlineStorage(InlineStorageImpl::None)
    }
}

unsafe impl<A, B> OwnedStorage<A, B> for InlineStorage<A, B> {
    #[inline]
    fn allocate_a(&mut self, value: A) -> *mut () {
        self.0 = InlineStorageImpl::A(value);
        2usize as *mut ()
    }

    #[inline]
    fn allocate_b(&mut self, value: B) -> *mut () {
        self.0 = InlineStorageImpl::B(value);
        2usize as *mut ()
    }

    #[inline]
    unsafe fn get_ptr_a<'a>(&'a self, _: *mut ()) -> &'a A {
        match self.0 {
            InlineStorageImpl::A(ref r) => r,
            _ => unreachable!(),
        }
    }

    #[inline]
    unsafe fn get_ptr_b<'a>(&'a self, _: *mut ()) -> &'a B {
        match self.0 {
            InlineStorageImpl::B(ref r) => r,
            _ => unreachable!(),
        }
    }

    #[inline]
    unsafe fn get_mut_a<'a>(&'a mut self, _: *mut ()) -> &'a mut A {
        match self.0 {
            InlineStorageImpl::A(ref mut r) => r,
            _ => unreachable!(),
        }
    }

    #[inline]
    unsafe fn get_mut_b<'a>(&'a mut self, _: *mut ()) -> &'a mut B {
        match self.0 {
            InlineStorageImpl::B(ref mut r) => r,
            _ => unreachable!(),
        }
    }

    #[inline]
    unsafe fn deallocate_a(&mut self, _: *mut ()) { }

    #[inline]
    unsafe fn deallocate_b(&mut self, _: *mut ()) { }

    #[inline]
    unsafe fn deallocate_into_a(&mut self, _: *mut ()) -> A {
        match mem::replace(&mut self.0, InlineStorageImpl::None) {
            InlineStorageImpl::A(v) => v,
            _ => unreachable!(),
        }
    }

    #[inline]
    unsafe fn deallocate_into_b(&mut self, _: *mut ()) -> B {
        match mem::replace(&mut self.0, InlineStorageImpl::None) {
            InlineStorageImpl::B(v) => v,
            _ => unreachable!(),
        }
    }

    #[inline]
    fn is_internal_storage() -> bool { true }
}

/// Causes the `OWNED` or `SHARED` value of a `Supercow` to be stored in a
/// `Box`.
///
/// This makes allocation of owned `Supercow`s more expensive, but incurs zero
/// space overhead within the `Supercow`. It also results in a faster `Deref`
/// implementation.
#[derive(Debug, Clone, Copy, Default)]
pub struct BoxedStorage;
unsafe impl<A, B> OwnedStorage<A, B> for BoxedStorage {
    #[inline]
    fn allocate_a(&mut self, value: A) -> *mut () {
        if mem::size_of::<A>() > 0 {
            let boxed = Box::new(value);
            let address = Box::into_raw(boxed);
            address as *mut ()
        } else {
            // Handle ZSTs specially, since `Box` "allocates" them at address
            // 1.
            2 as *mut ()
        }
    }

    #[inline]
    fn allocate_b(&mut self, value: B) -> *mut () {
        if mem::size_of::<B>() > 0 {
            let boxed = Box::new(value);
            let address = Box::into_raw(boxed);
            address as *mut ()
        } else {
            // Handle ZSTs specially, since `Box` "allocates" them at address
            // 1.
            2 as *mut ()
        }
    }

    #[inline]
    unsafe fn get_ptr_a<'a>(&'a self, ptr: *mut ()) -> &'a A {
        &*(ptr as *const A)
    }

    #[inline]
    unsafe fn get_ptr_b<'a>(&'a self, ptr: *mut ()) -> &'a B {
        &*(ptr as *const B)
    }

    #[inline]
    unsafe fn get_mut_a<'a>(&'a mut self, ptr: *mut ()) -> &'a mut A {
        &mut*(ptr as *mut A)
    }

    #[inline]
    unsafe fn get_mut_b<'a>(&'a mut self, ptr: *mut ()) -> &'a mut B {
        &mut*(ptr as *mut B)
    }

    #[inline]
    unsafe fn deallocate_a(&mut self, ptr: *mut ()) {
        if mem::size_of::<A>() > 0 {
            drop(Box::from_raw(ptr as *mut A))
        }
    }

    #[inline]
    unsafe fn deallocate_b(&mut self, ptr: *mut ()) {
        if mem::size_of::<B>() > 0 {
            drop(Box::from_raw(ptr as *mut B))
        }
    }

    #[inline]
    unsafe fn deallocate_into_a(&mut self, ptr: *mut ()) -> A {
        if mem::size_of::<A>() > 0 {
            *Box::from_raw(ptr as *mut A)
        } else {
            ptr::read(ptr as *mut A)
        }
    }

    #[inline]
    unsafe fn deallocate_into_b(&mut self, ptr: *mut ()) -> B {
        if mem::size_of::<B>() > 0 {
            *Box::from_raw(ptr as *mut B)
        } else {
            ptr::read(ptr as *mut B)
        }
    }

    #[inline]
    fn is_internal_storage() -> bool { false }
}
<commit_msg>Fix indentation.<commit_after>// Copyright 2016 Jason Lingle
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Miscelaneous things used to integrate other code with Supercow, but which
//! are not of interest to end users.

use std::borrow::Borrow;
use std::ffi::{CStr, OsStr};
use std::mem;
use std::path::Path;
use std::ptr;
use std::rc::Rc;
use std::slice;
use std::sync::Arc;

/// Marker trait indicating a `Deref`-like which always returns the same
/// reference.
///
/// This is not indended for general use outside Supercow. Notably, `Box` and
/// mundane references satisfy this trait's requirements, but deliberately do
/// not implement it. It is also not a subtrait of `Deref` due to some
/// additional special logic around boxes.
///
/// ## Unsafety
///
/// Behaviour is undefined if the implementation does not always return the
/// same reference from `deref()` for any particular implementing value
/// (including if that value is moved).
pub unsafe trait ConstDeref {
    /// The type this value dereferences to.
    type Target : ?Sized;
    /// Returns the (constant) value that this value dereferences to.
    fn const_deref(&self) -> &Self::Target;
}

unsafe impl<T : ?Sized> ConstDeref for Rc<T> {
    type Target = T;
    fn const_deref(&self) -> &T { self }
}

unsafe impl<T : ?Sized> ConstDeref for Arc<T> {
    type Target = T;
    fn const_deref(&self) -> &T { self }
}

unsafe impl<T : ConstDeref + ?Sized> ConstDeref for Box<T> {
    type Target = T::Target;
    fn const_deref(&self) -> &T::Target {
        (**self).const_deref()
    }
}

/// The maximum displacement (relative to the start of the object) that a
/// reference pointing into `self` from an instance of `SafeBorrow` may have.
///
/// This value is deliberately conservative to account for other memory layout
/// factors.
pub const MAX_INTERNAL_BORROW_DISPLACEMENT: usize = 2048;

/// Extension of `Borrow` used to allow `Supercow::to_mut()` to work safely.
///
/// ## Unsafety
///
/// Behaviour is undefined if the `borrow()` implementation may return a
/// reference into `self` which is more than `MAX_INTERNAL_BORROW_DISPLACEMENT`
/// bytes beyond the base of `self`.
pub unsafe trait SafeBorrow<T : ?Sized>: Borrow<T> {
    /// Given `ptr`, which was obtained from a prior call to `Self::borrow()`,
    /// return a value with the same nominal lifetime which is guaranteed to
    /// survive mutations to `Self`.
    ///
    /// Types which implement `Borrow` by pure, constant pointer arithmetic on
    /// `self` can simply return `ptr` unmodified. Other types typically need
    /// to provide some static reference, such as the empty string for `&str`.
    ///
    /// ## Unsafety
    ///
    /// Behaviour is undefined if this call returns `ptr`, but a mutation to
    /// `Self` could invalidate the reference.
    fn borrow_replacement<'a>(ptr: &'a T) -> &'a T;
}
unsafe impl<T : ?Sized> SafeBorrow<T> for T {
    fn borrow_replacement(ptr: &T) -> &T { ptr }
}
unsafe impl<B, T> SafeBorrow<[B]> for T where T : Borrow<[B]> {
    fn borrow_replacement(_: &[B]) -> &[B] {
        unsafe {
            slice::from_raw_parts(1 as usize as *const B, 0)
        }
    }
}
unsafe impl<T> SafeBorrow<str> for T where T : Borrow<str> {
    fn borrow_replacement(_: &str) -> &str { "" }
}
unsafe impl<T> SafeBorrow<CStr> for T
where T : Borrow<CStr> {
    fn borrow_replacement(_: &CStr) -> &CStr {
        static EMPTY_CSTR: &'static [u8] = &[0];
        unsafe {
            CStr::from_bytes_with_nul_unchecked(EMPTY_CSTR)
        }
    }
}
unsafe impl<T> SafeBorrow<OsStr> for T
where T : Borrow<OsStr> {
    fn borrow_replacement(_: &OsStr) -> &OsStr {
        OsStr::new("")
    }
}
unsafe impl<T> SafeBorrow<Path> for T
where T : Borrow<Path> {
    fn borrow_replacement(_: &Path) -> &Path {
        Path::new("")
    }
}

/// Marker trait identifying a reference type which begins with an absolute
/// address and contains no other address-dependent information.
///
/// `Supercow` expects to be able to read the first pointer-sized value of such
/// a reference and perform address arithmetic upon it.
///
/// There is no utility of applying this trait to anything other than a const
/// reference.
///
/// ## Unsafety
///
/// Behaviour is undefined if a marked type does not begin with a real pointer
/// to a value (with the usual exception of ZSTs, where the pointer does not
/// need to point to anything in particular) or if other parts of the type
/// contain address-dependent information.
///
/// Behaviour is undefined if the reference has any `Drop` implementation,
/// should a future Rust version make such things possible.
pub unsafe trait PointerFirstRef { }
unsafe impl<'a, T : Sized> PointerFirstRef for &'a T { }
unsafe impl<'a, T> PointerFirstRef for &'a [T] { }
unsafe impl<'a> PointerFirstRef for &'a str { }
unsafe impl<'a> PointerFirstRef for &'a ::std::ffi::CStr { }
unsafe impl<'a> PointerFirstRef for &'a ::std::ffi::OsStr { }
unsafe impl<'a> PointerFirstRef for &'a ::std::path::Path { }

/// Like `std::convert::From`, but without the blanket implementations that
/// cause problems for `supercow_features!`.
pub trait SharedFrom<T> {
    /// Converts the given `T` to `Self`.
    fn shared_from(t: T) -> Self;
}
impl <T> SharedFrom<Rc<T>> for Rc<T> {
    fn shared_from(t: Rc<T>) -> Rc<T> { t }
}
impl <T> SharedFrom<Arc<T>> for Arc<T> {
    fn shared_from(t: Arc<T>) -> Arc<T> { t }
}

/// Describes how an `OWNED` or `SHARED` value is stored in a `Supercow`.
///
/// All notes for `*_b` functions are the same as the corresponding `*_a`
/// functions.
///
/// ## Unsafety
///
/// `Supercow` relies strongly on the contracts of the functions in this trait
/// being implemented correctly.
pub unsafe trait OwnedStorage<A, B> : Default {
    /// Allocates the given owned value.
    ///
    /// `self` is a `Default`-initialised instance.
    ///
    /// Returns a pointer with 2-byte alignment.
    ///
    /// ## Unsafety
    ///
    /// Behaviour is undefined if this call returns a pointer with incorrect
    /// alignment.
    ///
    /// Behaviour is undefined if the returned value is an address inside
    /// `self` offset by more than `MAX_INTERNAL_BORROW_DISPLACEMENT/2` (note
    /// division by two).
    ///
    /// Behaviour is undefined if this returns a null pointer. (But the
    /// returned pointer does not need to actually point at anything.)
    fn allocate_a(&mut self, value: A) -> *mut ();
    /// See `allocate_a`.
    fn allocate_b(&mut self, value: B) -> *mut ();
    /// Extracts the immutable reference from the saved pointer and storage.
    ///
    /// ## Unsafety
    ///
    /// This call may assume that `ptr` is exactly a (2-byte-aligned) value it
    /// returned from `allocate_a`, and that `self` was initialised by a call
    /// to `allocate_a`.
    unsafe fn get_ptr_a<'a>(&'a self, ptr: *mut ()) -> &'a A;
    /// See `get_ptr_a`.
    unsafe fn get_ptr_b<'a>(&'a self, ptr: *mut ()) -> &'a B;
    /// Extracts the mutable reference from the saved pointer and storage.
    ///
    /// ## Unsafety
    ///
    /// This call may assume that `ptr` is exactly a (2-byte-aligned) value it
    /// returned from `allocate_a` and that `self` was initialised by a call to
    /// `allocate_a`.
    unsafe fn get_mut_a<'a>(&'a mut self, ptr: *mut ()) -> &'a mut A;
    /// See `get_mut_a`.
    unsafe fn get_mut_b<'a>(&'a mut self, ptr: *mut ()) -> &'a mut B;
    /// Releases any allocations that would not be released by `Stored`
    /// being dropped.
    ///
    /// ## Unsafety
    ///
    /// This call may assume that `ptr` is exactly a (2-byte-aligned) value it
    /// returned from `allocate_a`.
    ///
    /// Once this function is called, the given `ptr` is considered invalid and
    /// any further use is undefined.
    unsafe fn deallocate_a(&mut self, ptr: *mut ());
    /// See `deallocate_b`.
    unsafe fn deallocate_b(&mut self, ptr: *mut ());
    /// Like `deallocate_a()`, but also return the owned value.
    unsafe fn deallocate_into_a(&mut self, ptr: *mut ()) -> A;
    /// See `deallocate_into_a`.
    unsafe fn deallocate_into_b(&mut self, ptr: *mut ()) -> B;

    /// Returns whether this storage implementation ever causes the owned
    /// object to be stored internally to the `Supercow`.
    ///
    /// ## Unsafety
    ///
    /// Behaviour is undefined if this returns `false` but the owned value is
    /// stored within the `Supercow`.
    fn is_internal_storage() -> bool;
}

/// Causes the `OWNED` or `SHARED` value of a `Supercow` to be stored inline.
///
/// This makes allocation of owned `Supercow`s much faster, at the expense of
/// making the `Supercow` itself much bigger (since it now must contain the
/// whole object).
#[derive(Clone, Copy, Debug)]
pub struct InlineStorage<A, B>(InlineStorageImpl<A, B>);

#[derive(Clone, Copy, Debug)]
enum InlineStorageImpl<A, B> {
    None,
    A(A),
    B(B),
}

impl<A, B> Default for InlineStorage<A, B> {
    fn default() -> Self {
        InlineStorage(InlineStorageImpl::None)
    }
}

unsafe impl<A, B> OwnedStorage<A, B> for InlineStorage<A, B> {
    #[inline]
    fn allocate_a(&mut self, value: A) -> *mut () {
        self.0 = InlineStorageImpl::A(value);
        2usize as *mut ()
    }

    #[inline]
    fn allocate_b(&mut self, value: B) -> *mut () {
        self.0 = InlineStorageImpl::B(value);
        2usize as *mut ()
    }

    #[inline]
    unsafe fn get_ptr_a<'a>(&'a self, _: *mut ()) -> &'a A {
        match self.0 {
            InlineStorageImpl::A(ref r) => r,
            _ => unreachable!(),
        }
    }

    #[inline]
    unsafe fn get_ptr_b<'a>(&'a self, _: *mut ()) -> &'a B {
        match self.0 {
            InlineStorageImpl::B(ref r) => r,
            _ => unreachable!(),
        }
    }

    #[inline]
    unsafe fn get_mut_a<'a>(&'a mut self, _: *mut ()) -> &'a mut A {
        match self.0 {
            InlineStorageImpl::A(ref mut r) => r,
            _ => unreachable!(),
        }
    }

    #[inline]
    unsafe fn get_mut_b<'a>(&'a mut self, _: *mut ()) -> &'a mut B {
        match self.0 {
            InlineStorageImpl::B(ref mut r) => r,
            _ => unreachable!(),
        }
    }

    #[inline]
    unsafe fn deallocate_a(&mut self, _: *mut ()) { }

    #[inline]
    unsafe fn deallocate_b(&mut self, _: *mut ()) { }

    #[inline]
    unsafe fn deallocate_into_a(&mut self, _: *mut ()) -> A {
        match mem::replace(&mut self.0, InlineStorageImpl::None) {
            InlineStorageImpl::A(v) => v,
            _ => unreachable!(),
        }
    }

    #[inline]
    unsafe fn deallocate_into_b(&mut self, _: *mut ()) -> B {
        match mem::replace(&mut self.0, InlineStorageImpl::None) {
            InlineStorageImpl::B(v) => v,
            _ => unreachable!(),
        }
    }

    #[inline]
    fn is_internal_storage() -> bool { true }
}

/// Causes the `OWNED` or `SHARED` value of a `Supercow` to be stored in a
/// `Box`.
///
/// This makes allocation of owned `Supercow`s more expensive, but incurs zero
/// space overhead within the `Supercow`. It also results in a faster `Deref`
/// implementation.
#[derive(Debug, Clone, Copy, Default)]
pub struct BoxedStorage;
unsafe impl<A, B> OwnedStorage<A, B> for BoxedStorage {
    #[inline]
    fn allocate_a(&mut self, value: A) -> *mut () {
        if mem::size_of::<A>() > 0 {
            let boxed = Box::new(value);
            let address = Box::into_raw(boxed);
            address as *mut ()
        } else {
            // Handle ZSTs specially, since `Box` "allocates" them at address
            // 1.
            2 as *mut ()
        }
    }

    #[inline]
    fn allocate_b(&mut self, value: B) -> *mut () {
        if mem::size_of::<B>() > 0 {
            let boxed = Box::new(value);
            let address = Box::into_raw(boxed);
            address as *mut ()
        } else {
            // Handle ZSTs specially, since `Box` "allocates" them at address
            // 1.
            2 as *mut ()
        }
    }

    #[inline]
    unsafe fn get_ptr_a<'a>(&'a self, ptr: *mut ()) -> &'a A {
        &*(ptr as *const A)
    }

    #[inline]
    unsafe fn get_ptr_b<'a>(&'a self, ptr: *mut ()) -> &'a B {
        &*(ptr as *const B)
    }

    #[inline]
    unsafe fn get_mut_a<'a>(&'a mut self, ptr: *mut ()) -> &'a mut A {
        &mut*(ptr as *mut A)
    }

    #[inline]
    unsafe fn get_mut_b<'a>(&'a mut self, ptr: *mut ()) -> &'a mut B {
        &mut*(ptr as *mut B)
    }

    #[inline]
    unsafe fn deallocate_a(&mut self, ptr: *mut ()) {
        if mem::size_of::<A>() > 0 {
            drop(Box::from_raw(ptr as *mut A))
        }
    }

    #[inline]
    unsafe fn deallocate_b(&mut self, ptr: *mut ()) {
        if mem::size_of::<B>() > 0 {
            drop(Box::from_raw(ptr as *mut B))
        }
    }

    #[inline]
    unsafe fn deallocate_into_a(&mut self, ptr: *mut ()) -> A {
        if mem::size_of::<A>() > 0 {
            *Box::from_raw(ptr as *mut A)
        } else {
            ptr::read(ptr as *mut A)
        }
    }

    #[inline]
    unsafe fn deallocate_into_b(&mut self, ptr: *mut ()) -> B {
        if mem::size_of::<B>() > 0 {
            *Box::from_raw(ptr as *mut B)
        } else {
            ptr::read(ptr as *mut B)
        }
    }

    #[inline]
    fn is_internal_storage() -> bool { false }
}
<|endoftext|>


<commit_before>use std::slice;

extern crate libc;
use self::libc::{c_double, c_void, size_t};

use super::geo::{LineString, Point, Polygon};

use super::num_traits::{Float, Signed};
use super::polylabel;

/// Wrapper for a void pointer to a sequence of [`Array`](struct.Array.html)s, and the sequence length. Used for FFI.
///
/// Each sequence entry represents an inner Polygon ring.
#[repr(C)]
#[derive(Copy, Clone)]
pub struct WrapperArray {
    pub data: *const Array,
    pub len: size_t,
}

/// Wrapper for a void pointer to a sequence of 2-element arrays representing points, and the sequence length. Used for FFI.
///
/// Used for the outer Polygon shell. `data` is a `Vec<[c_double; 2]>`.
#[repr(C)]
pub struct Array {
    pub data: *const c_void,
    pub len: size_t,
}

/// FFI struct for returned optimum Polygon label position
#[repr(C)]
pub struct Position {
    pub x_pos: c_double,
    pub y_pos: c_double,
}

// convert a Polylabel result Point into values that can be sent across the FFI boundary
impl<T> From<Point<T>> for Position
where
    T: Float + Signed,
{
    fn from(point: Point<T>) -> Position {
        Position {
            x_pos: point.x().to_f64().unwrap() as c_double,
            y_pos: point.y().to_f64().unwrap() as c_double,
        }
    }
}

fn reconstitute(arr: &Array) -> Vec<[f64; 2]> {
    unsafe { slice::from_raw_parts(arr.data as *mut [f64; 2], arr.len).to_vec() }
}

fn reconstitute2(arr: WrapperArray) -> Vec<Vec<[f64; 2]>> {
    let arrays = unsafe { slice::from_raw_parts(arr.data as *mut Array, arr.len) };
    arrays.into_iter().map(|x| reconstitute(x)).collect()
}

/// FFI access to the [`polylabel`](fn.polylabel.html) function
///
/// Accepts three arguments:
///
/// - an exterior ring [`Array`](struct.Array.html)
/// - an interior rings [`WrapperArray`](struct.WrapperArray.html)
/// - a tolerance `c_double`.
#[no_mangle]
pub extern "C" fn polylabel_ffi(
    outer: Array,
    inners: WrapperArray,
    tolerance: c_double,
) -> Position {
    let exterior: Vec<[f64; 2]> =
        unsafe { slice::from_raw_parts(outer.data as *mut [c_double; 2], outer.len).to_vec() };
    let interior: Vec<Vec<[f64; 2]>> = reconstitute2(inners);
    let ls_ext: LineString<_> = exterior.into();
    let ls_int: Vec<LineString<c_double>> = interior.into_iter().map(|vec| vec.into()).collect();
    let poly = Polygon::new(ls_ext, ls_int);
    polylabel(&poly, &tolerance).into()
}

#[cfg(test)]
mod tests {
    use super::libc::{c_void, size_t};
    use super::{polylabel_ffi, reconstitute2, Array, WrapperArray};
    use geo::Point;
    use std::mem;

    // Only used for testing
    fn gen_array(v: Vec<[f64; 2]>) -> Array {
        let array = Array {
            data: v.as_ptr() as *const c_void,
            len: v.len() as size_t,
        };
        mem::forget(v);
        array
    }
    // only used for testing
    fn gen_wrapperarray(v: Vec<Vec<[f64; 2]>>) -> WrapperArray {
        let converted: Vec<Array> = v.into_iter().map(|x| gen_array(x)).collect();
        let array2 = WrapperArray {
            data: converted.as_ptr() as *const Array,
            len: converted.len() as size_t,
        };
        mem::forget(converted);
        array2
    }
    #[test]
    fn test_array() {
        let i_a = vec![[0.5, 0.5], [1.0, 1.0], [1.5, 0.5]];
        let i_b = vec![[0.55, 0.55], [0.8, 0.8], [1.2, 0.55]];
        let inners = vec![i_a, i_b];
        let array = gen_wrapperarray(inners);
        let rec_inners = reconstitute2(array);
        assert_eq!(rec_inners[0][2], [1.5, 0.5])
    }
    #[test]
    fn test_ffi() {
        let ext_vec = vec![
            [4.0, 1.0],
            [5.0, 2.0],
            [5.0, 3.0],
            [4.0, 4.0],
            [3.0, 4.0],
            [2.0, 3.0],
            [2.0, 2.0],
            [3.0, 1.0],
            [4.0, 1.0],
        ];
        let int_vec = vec![
            vec![[3.5, 3.5], [4.4, 2.0], [2.6, 2.0], [3.5, 3.5]],
            vec![[4.0, 3.0], [4.0, 3.2], [4.5, 3.2], [4.0, 3.0]],
        ];

        let outer = gen_array(ext_vec);
        let inners = gen_wrapperarray(int_vec);
        let res = polylabel_ffi(outer, inners, 0.1);
        let res_point = Point::new(res.x_pos, res.y_pos);
        assert_eq!(res_point, Point::new(3.125, 2.875));
    }

}
<commit_msg>Simplify Polygon creation<commit_after>use std::slice;

extern crate libc;
use self::libc::{c_double, c_void, size_t};

use super::geo::{LineString, Point, Polygon};

use super::num_traits::{Float, Signed};
use super::polylabel;

/// Wrapper for a void pointer to a sequence of [`Array`](struct.Array.html)s, and the sequence length. Used for FFI.
///
/// Each sequence entry represents an inner Polygon ring.
#[repr(C)]
#[derive(Copy, Clone)]
pub struct WrapperArray {
    pub data: *const Array,
    pub len: size_t,
}

/// Wrapper for a void pointer to a sequence of 2-element arrays representing points, and the sequence length. Used for FFI.
///
/// Used for the outer Polygon shell. `data` is a `Vec<[c_double; 2]>`.
#[repr(C)]
pub struct Array {
    pub data: *const c_void,
    pub len: size_t,
}

/// FFI struct for returned optimum Polygon label position
#[repr(C)]
pub struct Position {
    pub x_pos: c_double,
    pub y_pos: c_double,
}

// convert a Polylabel result Point into values that can be sent across the FFI boundary
impl<T> From<Point<T>> for Position
where
    T: Float + Signed,
{
    fn from(point: Point<T>) -> Position {
        Position {
            x_pos: point.x().to_f64().unwrap() as c_double,
            y_pos: point.y().to_f64().unwrap() as c_double,
        }
    }
}

fn reconstitute(arr: &Array) -> Vec<[f64; 2]> {
    unsafe { slice::from_raw_parts(arr.data as *mut [f64; 2], arr.len).to_vec() }
}

fn reconstitute2(arr: WrapperArray) -> Vec<Vec<[f64; 2]>> {
    let arrays = unsafe { slice::from_raw_parts(arr.data as *mut Array, arr.len) };
    arrays.into_iter().map(|x| reconstitute(x)).collect()
}

/// FFI access to the [`polylabel`](fn.polylabel.html) function
///
/// Accepts three arguments:
///
/// - an exterior ring [`Array`](struct.Array.html)
/// - an interior rings [`WrapperArray`](struct.WrapperArray.html)
/// - a tolerance `c_double`.
#[no_mangle]
pub extern "C" fn polylabel_ffi(
    outer: Array,
    inners: WrapperArray,
    tolerance: c_double,
) -> Position {
    let exterior: LineString<_> = unsafe {
        slice::from_raw_parts(outer.data as *mut [c_double; 2], outer.len)
            .to_vec()
            .into()
    };
    let interior: Vec<Vec<[f64; 2]>> = reconstitute2(inners);
    let ls_int: Vec<LineString<c_double>> = interior.into_iter().map(|vec| vec.into()).collect();
    let poly = Polygon::new(exterior, ls_int);
    polylabel(&poly, &tolerance).into()
}

#[cfg(test)]
mod tests {
    use super::libc::{c_void, size_t};
    use super::{polylabel_ffi, reconstitute2, Array, WrapperArray};
    use geo::Point;
    use std::mem;

    // Only used for testing
    fn gen_array(v: Vec<[f64; 2]>) -> Array {
        let array = Array {
            data: v.as_ptr() as *const c_void,
            len: v.len() as size_t,
        };
        mem::forget(v);
        array
    }
    // only used for testing
    fn gen_wrapperarray(v: Vec<Vec<[f64; 2]>>) -> WrapperArray {
        let converted: Vec<Array> = v.into_iter().map(|x| gen_array(x)).collect();
        let array2 = WrapperArray {
            data: converted.as_ptr() as *const Array,
            len: converted.len() as size_t,
        };
        mem::forget(converted);
        array2
    }
    #[test]
    fn test_array() {
        let i_a = vec![[0.5, 0.5], [1.0, 1.0], [1.5, 0.5]];
        let i_b = vec![[0.55, 0.55], [0.8, 0.8], [1.2, 0.55]];
        let inners = vec![i_a, i_b];
        let array = gen_wrapperarray(inners);
        let rec_inners = reconstitute2(array);
        assert_eq!(rec_inners[0][2], [1.5, 0.5])
    }
    #[test]
    fn test_ffi() {
        let ext_vec = vec![
            [4.0, 1.0],
            [5.0, 2.0],
            [5.0, 3.0],
            [4.0, 4.0],
            [3.0, 4.0],
            [2.0, 3.0],
            [2.0, 2.0],
            [3.0, 1.0],
            [4.0, 1.0],
        ];
        let int_vec = vec![
            vec![[3.5, 3.5], [4.4, 2.0], [2.6, 2.0], [3.5, 3.5]],
            vec![[4.0, 3.0], [4.0, 3.2], [4.5, 3.2], [4.0, 3.0]],
        ];

        let outer = gen_array(ext_vec);
        let inners = gen_wrapperarray(int_vec);
        let res = polylabel_ffi(outer, inners, 0.1);
        let res_point = Point::new(res.x_pos, res.y_pos);
        assert_eq!(res_point, Point::new(3.125, 2.875));
    }

}
<|endoftext|>


<commit_before>use defaults::{DEFAULT_DNS_SERVERS, DEFAULT_RECORD_TYPES};
use dns::{Source, Server};
use ungefiltert_surfen::{self, Server as UngefiltertServer};

use futures::{Future, future};
use resolv_conf;
use std::fs::File;
use std::io::Read;
use std::net::IpAddr;
use std::str::FromStr;
use tokio_core::reactor::Handle;
use trust_dns::rr::RecordType;

pub fn dns_servers(
    loop_handle: &Handle,
    servers: Option<Vec<String>>,
    use_predefined_server: bool,
    dont_use_local_servers: bool,
    ungefiltert_surfen_ids: Option<Vec<String>>,
) -> Box<Future<Item=Vec<Server>, Error=Error>> {
    let from_args = future::ok::<Vec<Server>, Error>({
        let mut dns_servers: Vec<Server> = Vec::new();
        if let Some(servers) = servers {
            dns_servers.extend(servers.into_iter()
                .map(|server| {
                    let (server, port_opt) = parse_server_port(&server).unwrap();
                    let port = port_opt.unwrap_or_else(|| 53u16);
                    let ip_addr = IpAddr::from_str(&server).unwrap();
                    Server::udp_from_with_port(ip_addr, port, Source::Additional)
                }));
        }
        if use_predefined_server {
            dns_servers.extend(DEFAULT_DNS_SERVERS.iter()
                .map(|&(server, desc)| {
                    let (server, port_opt) = parse_server_port(&server).unwrap();
                    let port = port_opt.unwrap_or_else(|| 53u16);
                    let ip_addr = IpAddr::from_str(&server).unwrap();
                    let mut s = Server::udp_from_with_port(ip_addr, port, Source::Predefined);
                    s.set_description(desc.to_string());
                    s
                }));
        }
        if !dont_use_local_servers {
            dns_servers.extend(dns_servers_from_resolv_conf().unwrap().into_iter()
                .map(|ip_addr| {
                    let mut s = Server::udp_from_with_port(ip_addr, 53u16, Source::Local);
                    s.set_description("local".to_string());
                    s
                })
            );
        }

        dns_servers
    }).map_err(move |e| {
        Error::with_chain(e, ErrorKind::ServerIpAddrParsingError)
    });

    let us: Vec<_> = ungefiltert_surfen_ids
        .unwrap_or_else(|| vec![])
        .iter()
        .map(|id| ungefiltert_surfen::retrieve_servers(loop_handle, id))
        .collect();
    let from_ungefiltert = future::join_all(us)
        .map(move |answers| {
            answers
                .into_iter()
                .fold(Vec::new(), |mut acc, servers: Vec<UngefiltertServer>| {
                    acc.extend(servers);
                    acc
                })
                .iter()
                .map(|server| {
                    let ip_addr = IpAddr::from_str(&server.ip).unwrap();
                    let mut s = Server::udp_from_with_port(ip_addr, 53u16, Source::Ungefiltert);
                    s.set_description(
                        format!("version={}, reliability={:.2}",
                                server.version.as_ref().map(String::as_ref).unwrap_or("unknown"),
                                server.reliability)
                    );
                    s
                })
                .collect()
        })
        .map_err(move |e| e.into());

    Box::new(from_args.join(from_ungefiltert).map(
        |(mut r1, r2): (Vec<_>, Vec<_>)| {
            r1.extend(r2);
            r1
        },
    ))
}

pub fn resolv_conf() -> Result<resolv_conf::Config> {
    let mut buf = Vec::with_capacity(4096);
    let mut f = File::open("/etc/resolv.conf").chain_err(
        || ErrorKind::ResolvConfError,
    )?;
    f.read_to_end(&mut buf).unwrap();
    let cfg = resolv_conf::Config::parse(&buf[..]).chain_err(|| {
        ErrorKind::ResolvConfError
    })?;

    Ok(cfg)
}

fn dns_servers_from_resolv_conf() -> Result<Vec<IpAddr>> {
    let cfg = resolv_conf()?;
    Ok(cfg.nameservers)
}

pub fn record_types(record_types: Option<Vec<String>>) -> Result<Vec<RecordType>> {
    let record_types = if let Some(rt) = record_types {
        rt.iter()
            .map(|rt| RecordType::from_str(&rt.to_uppercase()).unwrap())
            .collect()
    } else {
        DEFAULT_RECORD_TYPES
            .iter()
            .map(|rt| RecordType::from_str(&rt.to_uppercase()).unwrap())
            .collect()
    };

    Ok(record_types)
}

fn parse_server_port(server_port: &str) -> Result<(&str, Option<u16>)> {
    let mut splits: Vec<&str> = server_port.split(':').collect();
    match splits.len() {
        1 => Ok((splits.pop().unwrap(), None)),
        2 => {
            let port = splits.pop().unwrap().parse::<u16>()
                .chain_err(|| ErrorKind::ServerParsingError(server_port.to_string()))?;
            let server = splits.pop().unwrap();
            Ok((server, Some(port)))
        }
        _ => Err(Error::from_kind(ErrorKind::ServerParsingError(server_port.to_string())))
    }
}

pub fn domain_name_from_service_description(desc: &str) -> Result<String> {
    let splits: Vec<_> = desc.split(':').collect();

    // cf. https://github.com/rust-lang/rust/issues/23121
    let (service, proto, domain) = match splits.len() {
        2 => {
            let (service, domain) = (splits[0], splits[1]);
            (service, "tcp", domain)
        },
        3 => {
            let (service, mut proto, domain) = (splits[0], splits[1], splits[2]);
            proto = if proto.is_empty() { "tcp" } else { proto };
            (service, proto, domain)
        },
        _ => return Err(Error::from_kind(ErrorKind::ServiceDescriptionParsingError(desc.to_string())))
    };

    Ok(format!("_{}._{}.{}", service, proto, domain))
}

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

    #[test]
    fn domain_name_from_service_description_full() {
        let service_desc = "smtp:tcp:example.com";

        let domain_name = domain_name_from_service_description(service_desc).unwrap();

        assert_eq!(domain_name, "_smtp._tcp.example.com")
    }

    #[test]
    fn domain_name_from_service_description_wo_protocol() {
        let service_desc = "smtp::example.com";

        let domain_name = domain_name_from_service_description(service_desc).unwrap();

        assert_eq!(domain_name, "_smtp._tcp.example.com")
    }

    #[test]
    fn domain_name_from_service_description_omitting_protocol() {
        let service_desc = "smtp:example.com";

        let domain_name = domain_name_from_service_description(service_desc).unwrap();

        assert_eq!(domain_name, "_smtp._tcp.example.com")
    }

    #[test]
    fn domain_name_from_service_description_fails() {
        let service_desc = "smtp_example.com";

        let domain_name = domain_name_from_service_description(service_desc);

        assert!(domain_name.is_err());
    }

    #[test]
    fn parse_server_port_server_only() {
        let srv_str = "192.168.0.1";

        let (server, port_opt) = parse_server_port(srv_str).unwrap();

        assert_eq!(server, srv_str);
        assert_eq!(port_opt, None)
    }

    #[test]
    fn parse_server_port_server_n_port() {
        let srv_str = "192.168.0.1:53";

        let (server, port_opt) = parse_server_port(srv_str).unwrap();

        assert_eq!(server, "192.168.0.1");
        assert_eq!(port_opt, Some(53))
    }

    #[test]
    fn parse_server_port_server_server_n_port() {
        let srv_str = ":xx";

        let result = parse_server_port(srv_str);

        assert!(result.is_err())
    }

    #[test]
    fn parse_server_port_server_n_failed_port_1() {
        let srv_str = "192.168.0.1:xx";

        let result = parse_server_port(srv_str);

        assert!(result.is_err())
    }

    #[test]
    fn parse_server_port_server_n_failed_port_2() {
        let srv_str = "192.168.0.1:";

        let result = parse_server_port(srv_str);

        assert!(result.is_err())
    }
}

error_chain! {
    errors {
        ResolvConfError {
            description("failed to parse /etc/resolv.conf")
            display("failed to parse /etc/resolv.cons")
        }

        ServerIpAddrParsingError {
            description("failed to parse server IP address")
            display("failed to parse server IP address")
        }

        ServerParsingError(srv_str: String) {
            description("failed to parse server string")
            display("failed to parse server string '{}'", srv_str)
        }

        ServiceDescriptionParsingError(serv_desc: String) {
            description("failed to parse service decription")
            display("failed to parse service decription '{}'", serv_desc)
        }

        ResoureRecordTypeParsingError {
            description("failed to parse resource record type")
            display("failed to parse resource record type")
        }
    }

    links {
        Ungefiltert(ungefiltert_surfen::Error, ungefiltert_surfen::ErrorKind);
    }
}
<commit_msg>Add parsing issue for<commit_after>use defaults::{DEFAULT_DNS_SERVERS, DEFAULT_RECORD_TYPES};
use dns::{Source, Server};
use ungefiltert_surfen::{self, Server as UngefiltertServer};

use futures::{Future, future};
use resolv_conf;
use std::fs::File;
use std::io::Read;
use std::net::IpAddr;
use std::str::FromStr;
use tokio_core::reactor::Handle;
use trust_dns::rr::RecordType;

pub fn dns_servers(
    loop_handle: &Handle,
    servers: Option<Vec<String>>,
    use_predefined_server: bool,
    dont_use_local_servers: bool,
    ungefiltert_surfen_ids: Option<Vec<String>>,
) -> Box<Future<Item=Vec<Server>, Error=Error>> {
    let from_args = future::ok::<Vec<Server>, Error>({
        let mut dns_servers: Vec<Server> = Vec::new();
        if let Some(servers) = servers {
            dns_servers.extend(servers.into_iter()
                .map(|server| {
                    let (server, port_opt) = parse_server_port(&server).unwrap();
                    let port = port_opt.unwrap_or_else(|| 53u16);
                    let ip_addr = IpAddr::from_str(&server).unwrap();
                    Server::udp_from_with_port(ip_addr, port, Source::Additional)
                }));
        }
        if use_predefined_server {
            dns_servers.extend(DEFAULT_DNS_SERVERS.iter()
                .map(|&(server, desc)| {
                    let (server, port_opt) = parse_server_port(&server).unwrap();
                    let port = port_opt.unwrap_or_else(|| 53u16);
                    let ip_addr = IpAddr::from_str(&server).unwrap();
                    let mut s = Server::udp_from_with_port(ip_addr, port, Source::Predefined);
                    s.set_description(desc.to_string());
                    s
                }));
        }
        if !dont_use_local_servers {
            dns_servers.extend(dns_servers_from_resolv_conf().unwrap().into_iter()
                .map(|ip_addr| {
                    let mut s = Server::udp_from_with_port(ip_addr, 53u16, Source::Local);
                    s.set_description("local".to_string());
                    s
                })
            );
        }

        dns_servers
    }).map_err(move |e| {
        Error::with_chain(e, ErrorKind::ServerIpAddrParsingError)
    });

    let us: Vec<_> = ungefiltert_surfen_ids
        .unwrap_or_else(|| vec![])
        .iter()
        .map(|id| ungefiltert_surfen::retrieve_servers(loop_handle, id))
        .collect();
    let from_ungefiltert = future::join_all(us)
        .map(move |answers| {
            answers
                .into_iter()
                .fold(Vec::new(), |mut acc, servers: Vec<UngefiltertServer>| {
                    acc.extend(servers);
                    acc
                })
                .iter()
                .map(|server| {
                    let ip_addr = IpAddr::from_str(&server.ip).unwrap();
                    let mut s = Server::udp_from_with_port(ip_addr, 53u16, Source::Ungefiltert);
                    s.set_description(
                        format!("version={}, reliability={:.2}",
                                server.version.as_ref().map(String::as_ref).unwrap_or("unknown"),
                                server.reliability)
                    );
                    s
                })
                .collect()
        })
        .map_err(move |e| e.into());

    Box::new(from_args.join(from_ungefiltert).map(
        |(mut r1, r2): (Vec<_>, Vec<_>)| {
            r1.extend(r2);
            r1
        },
    ))
}

pub fn resolv_conf() -> Result<resolv_conf::Config> {
    let mut buf = Vec::with_capacity(4096);
    let mut f = File::open("/etc/resolv.conf").chain_err(
        || ErrorKind::ResolvConfError,
    )?;
    f.read_to_end(&mut buf).unwrap();
    let cfg = resolv_conf::Config::parse(&buf[..]).chain_err(|| {
        ErrorKind::ResolvConfError
    })?;

    Ok(cfg)
}

fn dns_servers_from_resolv_conf() -> Result<Vec<IpAddr>> {
    let cfg = resolv_conf()?;
    Ok(cfg.nameservers)
}

pub fn record_types(record_types: Option<Vec<String>>) -> Result<Vec<RecordType>> {
    let record_types = if let Some(rt) = record_types {
        rt.iter()
            .map(|rt| RecordType::from_str(&rt.to_uppercase()).unwrap())
            .collect()
    } else {
        DEFAULT_RECORD_TYPES
            .iter()
            .map(|rt| RecordType::from_str(&rt.to_uppercase()).unwrap())
            .collect()
    };

    Ok(record_types)
}

// TODO: Does not work for IPv6
fn parse_server_port(server_port: &str) -> Result<(&str, Option<u16>)> {
    let mut splits: Vec<&str> = server_port.split(':').collect();
    match splits.len() {
        1 => Ok((splits.pop().unwrap(), None)),
        2 => {
            let port = splits.pop().unwrap().parse::<u16>()
                .chain_err(|| ErrorKind::ServerParsingError(server_port.to_string()))?;
            let server = splits.pop().unwrap();
            Ok((server, Some(port)))
        }
        _ => Err(Error::from_kind(ErrorKind::ServerParsingError(server_port.to_string())))
    }
}

pub fn domain_name_from_service_description(desc: &str) -> Result<String> {
    let splits: Vec<_> = desc.split(':').collect();

    // cf. https://github.com/rust-lang/rust/issues/23121
    let (service, proto, domain) = match splits.len() {
        2 => {
            let (service, domain) = (splits[0], splits[1]);
            (service, "tcp", domain)
        },
        3 => {
            let (service, mut proto, domain) = (splits[0], splits[1], splits[2]);
            proto = if proto.is_empty() { "tcp" } else { proto };
            (service, proto, domain)
        },
        _ => return Err(Error::from_kind(ErrorKind::ServiceDescriptionParsingError(desc.to_string())))
    };

    Ok(format!("_{}._{}.{}", service, proto, domain))
}

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

    #[test]
    fn domain_name_from_service_description_full() {
        let service_desc = "smtp:tcp:example.com";

        let domain_name = domain_name_from_service_description(service_desc).unwrap();

        assert_eq!(domain_name, "_smtp._tcp.example.com")
    }

    #[test]
    fn domain_name_from_service_description_wo_protocol() {
        let service_desc = "smtp::example.com";

        let domain_name = domain_name_from_service_description(service_desc).unwrap();

        assert_eq!(domain_name, "_smtp._tcp.example.com")
    }

    #[test]
    fn domain_name_from_service_description_omitting_protocol() {
        let service_desc = "smtp:example.com";

        let domain_name = domain_name_from_service_description(service_desc).unwrap();

        assert_eq!(domain_name, "_smtp._tcp.example.com")
    }

    #[test]
    fn domain_name_from_service_description_fails() {
        let service_desc = "smtp_example.com";

        let domain_name = domain_name_from_service_description(service_desc);

        assert!(domain_name.is_err());
    }

    #[test]
    fn parse_server_port_server_only() {
        let srv_str = "192.168.0.1";

        let (server, port_opt) = parse_server_port(srv_str).unwrap();

        assert_eq!(server, srv_str);
        assert_eq!(port_opt, None)
    }

    #[test]
    fn parse_server_port_server_n_port() {
        let srv_str = "192.168.0.1:53";

        let (server, port_opt) = parse_server_port(srv_str).unwrap();

        assert_eq!(server, "192.168.0.1");
        assert_eq!(port_opt, Some(53))
    }

    #[test]
    fn parse_server_port_server_server_n_port() {
        let srv_str = ":xx";

        let result = parse_server_port(srv_str);

        assert!(result.is_err())
    }

    #[test]
    fn parse_server_port_server_n_failed_port_1() {
        let srv_str = "192.168.0.1:xx";

        let result = parse_server_port(srv_str);

        assert!(result.is_err())
    }

    #[test]
    fn parse_server_port_server_n_failed_port_2() {
        let srv_str = "192.168.0.1:";

        let result = parse_server_port(srv_str);

        assert!(result.is_err())
    }
}

error_chain! {
    errors {
        ResolvConfError {
            description("failed to parse /etc/resolv.conf")
            display("failed to parse /etc/resolv.cons")
        }

        ServerIpAddrParsingError {
            description("failed to parse server IP address")
            display("failed to parse server IP address")
        }

        ServerParsingError(srv_str: String) {
            description("failed to parse server string")
            display("failed to parse server string '{}'", srv_str)
        }

        ServiceDescriptionParsingError(serv_desc: String) {
            description("failed to parse service decription")
            display("failed to parse service decription '{}'", serv_desc)
        }

        ResoureRecordTypeParsingError {
            description("failed to parse resource record type")
            display("failed to parse resource record type")
        }
    }

    links {
        Ungefiltert(ungefiltert_surfen::Error, ungefiltert_surfen::ErrorKind);
    }
}
<|endoftext|>


<commit_before>#![doc(html_root_url = "https://docs.rs/mio/0.6.16")]
#![deny(missing_docs, missing_debug_implementations)]
#![cfg_attr(test, deny(warnings))]

// Many of mio's public methods violate this lint, but they can't be fixed
// without a breaking change.
#![cfg_attr(feature = "cargo-clippy", allow(clippy::trivially_copy_pass_by_ref))]

//! A fast, low-level IO library for Rust focusing on non-blocking APIs, event
//! notification, and other useful utilities for building high performance IO
//! apps.
//!
//! # Goals
//!
//! * Fast - minimal overhead over the equivalent OS facilities (epoll, kqueue, etc...)
//! * Zero allocations
//! * A scalable readiness-based API, similar to epoll on Linux
//! * Design to allow for stack allocated buffers when possible (avoid double buffering).
//! * Provide utilities such as a timers, a notification channel, buffer abstractions, and a slab.
//!
//! # Platforms
//!
//! Currently supported platforms:
//!
//! * Linux
//! * OS X
//! * Windows
//! * FreeBSD
//! * NetBSD
//! * Android
//! * iOS
//!
//! mio can handle interfacing with each of the event notification systems of the aforementioned platforms. The details of
//! their implementation are further discussed in [`Poll`].
//!
//! # Usage
//!
//! Using mio starts by creating a [`Poll`], which reads events from the OS and
//! put them into [`Events`]. You can handle IO events from the OS with it.
//!
//! For more detail, see [`Poll`].
//!
//! [`Poll`]: struct.Poll.html
//! [`Events`]: struct.Events.html
//!
//! # Example
//!
//! ```
//! use mio::*;
//! use mio::net::{TcpListener, TcpStream};
//!
//! // Setup some tokens to allow us to identify which event is
//! // for which socket.
//! const SERVER: Token = Token(0);
//! const CLIENT: Token = Token(1);
//!
//! let addr = "127.0.0.1:13265".parse().unwrap();
//!
//! // Setup the server socket
//! let server = TcpListener::bind(&addr).unwrap();
//!
//! // Create a poll instance
//! let poll = Poll::new().unwrap();
//!
//! // Start listening for incoming connections
//! poll.register(&server, SERVER, Ready::readable(),
//!               PollOpt::edge()).unwrap();
//!
//! // Setup the client socket
//! let sock = TcpStream::connect(&addr).unwrap();
//!
//! // Register the socket
//! poll.register(&sock, CLIENT, Ready::readable(),
//!               PollOpt::edge()).unwrap();
//!
//! // Create storage for events
//! let mut events = Events::with_capacity(1024);
//!
//! loop {
//!     poll.poll(&mut events, None).unwrap();
//!
//!     for event in events.iter() {
//!         match event.token() {
//!             SERVER => {
//!                 // Accept and drop the socket immediately, this will close
//!                 // the socket and notify the client of the EOF.
//!                 let _ = server.accept();
//!             }
//!             CLIENT => {
//!                 // The server just shuts down the socket, let's just exit
//!                 // from our event loop.
//!                 return;
//!             }
//!             _ => unreachable!(),
//!         }
//!     }
//! }
//!
//! ```

extern crate net2;
extern crate iovec;
extern crate slab;

#[cfg(target_os = "fuchsia")]
extern crate fuchsia_zircon as zircon;
#[cfg(target_os = "fuchsia")]
extern crate fuchsia_zircon_sys as zircon_sys;

#[cfg(unix)]
extern crate libc;

#[cfg(windows)]
extern crate miow;

#[cfg(windows)]
extern crate winapi;

#[cfg(windows)]
extern crate kernel32;

#[macro_use]
extern crate log;

mod event_imp;
mod io;
mod poll;
mod sys;
mod token;
mod lazycell;

pub mod net;

#[deprecated(since = "0.6.5", note = "use mio-extras instead")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub mod channel;

#[deprecated(since = "0.6.5", note = "use mio-extras instead")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub mod timer;

#[deprecated(since = "0.6.5", note = "update to use `Poll`")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub mod deprecated;

#[deprecated(since = "0.6.5", note = "use iovec crate directly")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub use iovec::IoVec;

#[deprecated(since = "0.6.6", note = "use net module instead")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub mod tcp {
    pub use net::{TcpListener, TcpStream};
    pub use std::net::Shutdown;
}

#[deprecated(since = "0.6.6", note = "use net module instead")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub mod udp;

pub use poll::{
    Poll,
    Registration,
    SetReadiness,
};
pub use event_imp::{
    PollOpt,
    Ready,
};
pub use token::Token;

pub mod event {
    //! Readiness event types and utilities.

    pub use super::poll::{Events, Iter};
    pub use super::event_imp::{Event, Evented};
}

pub use event::{
    Events,
};

#[deprecated(since = "0.6.5", note = "use events:: instead")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub use event::{Event, Evented};

#[deprecated(since = "0.6.5", note = "use events::Iter instead")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub use poll::Iter as EventsIter;

#[deprecated(since = "0.6.5", note = "std::io::Error can avoid the allocation now")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub use io::deprecated::would_block;

#[cfg(all(unix, not(target_os = "fuchsia")))]
pub mod unix {
    //! Unix only extensions
    pub use sys::{
        EventedFd,
    };
    pub use sys::unix::UnixReady;
}

#[cfg(target_os = "fuchsia")]
pub mod fuchsia {
    //! Fuchsia-only extensions
    //!
    //! # Stability
    //!
    //! This module depends on the [magenta-sys crate](https://crates.io/crates/magenta-sys)
    //! and so might introduce breaking changes, even on minor releases,
    //! so long as that crate remains unstable.
    pub use sys::{
        EventedHandle,
    };
    pub use sys::fuchsia::{FuchsiaReady, zx_signals_t};
}

/// Windows-only extensions to the mio crate.
///
/// Mio on windows is currently implemented with IOCP for a high-performance
/// implementation of asynchronous I/O. Mio then provides TCP and UDP as sample
/// bindings for the system to connect networking types to asynchronous I/O. On
/// Unix this scheme is then also extensible to all other file descriptors with
/// the `EventedFd` type, but on Windows no such analog is available. The
/// purpose of this module, however, is to similarly provide a mechanism for
/// foreign I/O types to get hooked up into the IOCP event loop.
///
/// This module provides two types for interfacing with a custom IOCP handle:
///
/// * `Binding` - this type is intended to govern binding with mio's `Poll`
///   type. Each I/O object should contain an instance of `Binding` that's
///   interfaced with for the implementation of the `Evented` trait. The
///   `register`, `reregister`, and `deregister` methods for the `Evented` trait
///   all have rough analogs with `Binding`.
///
///   Note that this type **does not handle readiness**. That is, this type does
///   not handle whether sockets are readable/writable/etc. It's intended that
///   IOCP types will internally manage this state with a `SetReadiness` type
///   from the `poll` module. The `SetReadiness` is typically lazily created on
///   the first time that `Evented::register` is called and then stored in the
///   I/O object.
///
///   Also note that for types which represent streams of bytes the mio
///   interface of *readiness* doesn't map directly to the Windows model of
///   *completion*. This means that types will have to perform internal
///   buffering to ensure that a readiness interface can be provided. For a
///   sample implementation see the TCP/UDP modules in mio itself.
///
/// * `Overlapped` - this type is intended to be used as the concrete instances
///   of the `OVERLAPPED` type that most win32 methods expect. It's crucial, for
///   safety, that all asynchronous operations are initiated with an instance of
///   `Overlapped` and not another instantiation of `OVERLAPPED`.
///
///   Mio's `Overlapped` type is created with a function pointer that receives
///   a `OVERLAPPED_ENTRY` type when called. This `OVERLAPPED_ENTRY` type is
///   defined in the `winapi` crate. Whenever a completion is posted to an IOCP
///   object the `OVERLAPPED` that was signaled will be interpreted as
///   `Overlapped` in the mio crate and this function pointer will be invoked.
///   Through this function pointer, and through the `OVERLAPPED` pointer,
///   implementations can handle management of I/O events.
///
/// When put together these two types enable custom Windows handles to be
/// registered with mio's event loops. The `Binding` type is used to associate
/// handles and the `Overlapped` type is used to execute I/O operations. When
/// the I/O operations are completed a custom function pointer is called which
/// typically modifies a `SetReadiness` set by `Evented` methods which will get
/// later hooked into the mio event loop.
#[cfg(windows)]
pub mod windows {

    pub use sys::{Overlapped, Binding};
}

#[cfg(feature = "with-deprecated")]
mod convert {
    use std::time::Duration;

    const NANOS_PER_MILLI: u32 = 1_000_000;
    const MILLIS_PER_SEC: u64 = 1_000;

    /// Convert a `Duration` to milliseconds, rounding up and saturating at
    /// `u64::MAX`.
    ///
    /// The saturating is fine because `u64::MAX` milliseconds are still many
    /// million years.
    pub fn millis(duration: Duration) -> u64 {
        // Round up.
        let millis = (duration.subsec_nanos() + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI;
        duration.as_secs().saturating_mul(MILLIS_PER_SEC).saturating_add(u64::from(millis))
    }
}
<commit_msg>docs: update lib.rs comment to mirror README.md (#906)<commit_after>#![doc(html_root_url = "https://docs.rs/mio/0.6.16")]
#![deny(missing_docs, missing_debug_implementations)]
#![cfg_attr(test, deny(warnings))]

// Many of mio's public methods violate this lint, but they can't be fixed
// without a breaking change.
#![cfg_attr(feature = "cargo-clippy", allow(clippy::trivially_copy_pass_by_ref))]

//! A fast, low-level IO library for Rust focusing on non-blocking APIs, event
//! notification, and other useful utilities for building high performance IO
//! apps.
//!
//! # Features
//!
//! * Non-blocking TCP, UDP
//! * I/O event notification queue backed by epoll, kqueue, and IOCP
//! * Zero allocations at runtime
//! * Platform specific extensions
//!
//! # Non-goals
//!
//! The following are specifically omitted from Mio and are left to the user or higher-level libraries.
//!
//! * File operations
//! * Thread pools / multi-threaded event loop
//! * Timers
//!
//! # Platforms
//!
//! Currently supported platforms:
//!
//! * Linux
//! * OS X
//! * Windows
//! * FreeBSD
//! * NetBSD
//! * Android
//! * iOS
//!
//! mio can handle interfacing with each of the event notification systems of the aforementioned platforms. The details of
//! their implementation are further discussed in [`Poll`].
//!
//! # Usage
//!
//! Using mio starts by creating a [`Poll`], which reads events from the OS and
//! put them into [`Events`]. You can handle IO events from the OS with it.
//!
//! For more detail, see [`Poll`].
//!
//! [`Poll`]: struct.Poll.html
//! [`Events`]: struct.Events.html
//!
//! # Example
//!
//! ```
//! use mio::*;
//! use mio::net::{TcpListener, TcpStream};
//!
//! // Setup some tokens to allow us to identify which event is
//! // for which socket.
//! const SERVER: Token = Token(0);
//! const CLIENT: Token = Token(1);
//!
//! let addr = "127.0.0.1:13265".parse().unwrap();
//!
//! // Setup the server socket
//! let server = TcpListener::bind(&addr).unwrap();
//!
//! // Create a poll instance
//! let poll = Poll::new().unwrap();
//!
//! // Start listening for incoming connections
//! poll.register(&server, SERVER, Ready::readable(),
//!               PollOpt::edge()).unwrap();
//!
//! // Setup the client socket
//! let sock = TcpStream::connect(&addr).unwrap();
//!
//! // Register the socket
//! poll.register(&sock, CLIENT, Ready::readable(),
//!               PollOpt::edge()).unwrap();
//!
//! // Create storage for events
//! let mut events = Events::with_capacity(1024);
//!
//! loop {
//!     poll.poll(&mut events, None).unwrap();
//!
//!     for event in events.iter() {
//!         match event.token() {
//!             SERVER => {
//!                 // Accept and drop the socket immediately, this will close
//!                 // the socket and notify the client of the EOF.
//!                 let _ = server.accept();
//!             }
//!             CLIENT => {
//!                 // The server just shuts down the socket, let's just exit
//!                 // from our event loop.
//!                 return;
//!             }
//!             _ => unreachable!(),
//!         }
//!     }
//! }
//!
//! ```

extern crate net2;
extern crate iovec;
extern crate slab;

#[cfg(target_os = "fuchsia")]
extern crate fuchsia_zircon as zircon;
#[cfg(target_os = "fuchsia")]
extern crate fuchsia_zircon_sys as zircon_sys;

#[cfg(unix)]
extern crate libc;

#[cfg(windows)]
extern crate miow;

#[cfg(windows)]
extern crate winapi;

#[cfg(windows)]
extern crate kernel32;

#[macro_use]
extern crate log;

mod event_imp;
mod io;
mod poll;
mod sys;
mod token;
mod lazycell;

pub mod net;

#[deprecated(since = "0.6.5", note = "use mio-extras instead")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub mod channel;

#[deprecated(since = "0.6.5", note = "use mio-extras instead")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub mod timer;

#[deprecated(since = "0.6.5", note = "update to use `Poll`")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub mod deprecated;

#[deprecated(since = "0.6.5", note = "use iovec crate directly")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub use iovec::IoVec;

#[deprecated(since = "0.6.6", note = "use net module instead")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub mod tcp {
    pub use net::{TcpListener, TcpStream};
    pub use std::net::Shutdown;
}

#[deprecated(since = "0.6.6", note = "use net module instead")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub mod udp;

pub use poll::{
    Poll,
    Registration,
    SetReadiness,
};
pub use event_imp::{
    PollOpt,
    Ready,
};
pub use token::Token;

pub mod event {
    //! Readiness event types and utilities.

    pub use super::poll::{Events, Iter};
    pub use super::event_imp::{Event, Evented};
}

pub use event::{
    Events,
};

#[deprecated(since = "0.6.5", note = "use events:: instead")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub use event::{Event, Evented};

#[deprecated(since = "0.6.5", note = "use events::Iter instead")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub use poll::Iter as EventsIter;

#[deprecated(since = "0.6.5", note = "std::io::Error can avoid the allocation now")]
#[cfg(feature = "with-deprecated")]
#[doc(hidden)]
pub use io::deprecated::would_block;

#[cfg(all(unix, not(target_os = "fuchsia")))]
pub mod unix {
    //! Unix only extensions
    pub use sys::{
        EventedFd,
    };
    pub use sys::unix::UnixReady;
}

#[cfg(target_os = "fuchsia")]
pub mod fuchsia {
    //! Fuchsia-only extensions
    //!
    //! # Stability
    //!
    //! This module depends on the [magenta-sys crate](https://crates.io/crates/magenta-sys)
    //! and so might introduce breaking changes, even on minor releases,
    //! so long as that crate remains unstable.
    pub use sys::{
        EventedHandle,
    };
    pub use sys::fuchsia::{FuchsiaReady, zx_signals_t};
}

/// Windows-only extensions to the mio crate.
///
/// Mio on windows is currently implemented with IOCP for a high-performance
/// implementation of asynchronous I/O. Mio then provides TCP and UDP as sample
/// bindings for the system to connect networking types to asynchronous I/O. On
/// Unix this scheme is then also extensible to all other file descriptors with
/// the `EventedFd` type, but on Windows no such analog is available. The
/// purpose of this module, however, is to similarly provide a mechanism for
/// foreign I/O types to get hooked up into the IOCP event loop.
///
/// This module provides two types for interfacing with a custom IOCP handle:
///
/// * `Binding` - this type is intended to govern binding with mio's `Poll`
///   type. Each I/O object should contain an instance of `Binding` that's
///   interfaced with for the implementation of the `Evented` trait. The
///   `register`, `reregister`, and `deregister` methods for the `Evented` trait
///   all have rough analogs with `Binding`.
///
///   Note that this type **does not handle readiness**. That is, this type does
///   not handle whether sockets are readable/writable/etc. It's intended that
///   IOCP types will internally manage this state with a `SetReadiness` type
///   from the `poll` module. The `SetReadiness` is typically lazily created on
///   the first time that `Evented::register` is called and then stored in the
///   I/O object.
///
///   Also note that for types which represent streams of bytes the mio
///   interface of *readiness* doesn't map directly to the Windows model of
///   *completion*. This means that types will have to perform internal
///   buffering to ensure that a readiness interface can be provided. For a
///   sample implementation see the TCP/UDP modules in mio itself.
///
/// * `Overlapped` - this type is intended to be used as the concrete instances
///   of the `OVERLAPPED` type that most win32 methods expect. It's crucial, for
///   safety, that all asynchronous operations are initiated with an instance of
///   `Overlapped` and not another instantiation of `OVERLAPPED`.
///
///   Mio's `Overlapped` type is created with a function pointer that receives
///   a `OVERLAPPED_ENTRY` type when called. This `OVERLAPPED_ENTRY` type is
///   defined in the `winapi` crate. Whenever a completion is posted to an IOCP
///   object the `OVERLAPPED` that was signaled will be interpreted as
///   `Overlapped` in the mio crate and this function pointer will be invoked.
///   Through this function pointer, and through the `OVERLAPPED` pointer,
///   implementations can handle management of I/O events.
///
/// When put together these two types enable custom Windows handles to be
/// registered with mio's event loops. The `Binding` type is used to associate
/// handles and the `Overlapped` type is used to execute I/O operations. When
/// the I/O operations are completed a custom function pointer is called which
/// typically modifies a `SetReadiness` set by `Evented` methods which will get
/// later hooked into the mio event loop.
#[cfg(windows)]
pub mod windows {

    pub use sys::{Overlapped, Binding};
}

#[cfg(feature = "with-deprecated")]
mod convert {
    use std::time::Duration;

    const NANOS_PER_MILLI: u32 = 1_000_000;
    const MILLIS_PER_SEC: u64 = 1_000;

    /// Convert a `Duration` to milliseconds, rounding up and saturating at
    /// `u64::MAX`.
    ///
    /// The saturating is fine because `u64::MAX` milliseconds are still many
    /// million years.
    pub fn millis(duration: Duration) -> u64 {
        // Round up.
        let millis = (duration.subsec_nanos() + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI;
        duration.as_secs().saturating_mul(MILLIS_PER_SEC).saturating_add(u64::from(millis))
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;

use std::collections::btree_map::BTreeMap;
use std::net::{SocketAddr, ToSocketAddrs};
use std::fs::File;
use std::io::Write;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_serialize::json::{self, ToJson, Json};

#[derive(Debug)]
pub struct ChatUser {
	pub name: String,
	pub poster: SocketAddr,
}

#[derive(RustcDecodable)]
pub struct ChatMessage {
	pub sender: ChatUser,
	pub value: String,
}

impl ChatUser {
	//TODO: look it up somewhere, maybe?
	/// Creates a user defined by the supplied arguments
	pub fn get<Addr: ToSocketAddrs>(name: String, poster: Addr) -> ChatUser {
		ChatUser{
			name: name,
			poster: poster.to_socket_addrs().ok().unwrap().next().unwrap(),  //TODO: This should probably be handled, eh?
		}
	}
}

impl Decodable for ChatUser {
	fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
		let name = try!(d.read_str());
		let poster: &str = &*&try!(d.read_str());
		File::create("lel").ok().unwrap().write_fmt(format_args!("{}\n{}", name, poster));
		Ok(ChatUser::get(name, poster))
	}
}

impl ToJson for ChatUser {
	fn to_json(&self) -> Json {
		let mut d = BTreeMap::new();
		// All standard types implement `to_json()`, so use it
		d.insert("name".to_string(), self.name.to_json());
		d.insert("poster".to_string(), self.poster.to_string().to_json());
		Json::Object(d)
	}
}

/*impl Encodable for ChatUser {
	fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
		try!(s.emit_str(&*&self.name));
		try!(s.emit_str(&*&format!("{}", self.poster)));
		Ok(())
	}
}*/

#[test]
fn asdf() {
	let cu = ChatUser::get("keke".to_string(), "127.0.0.1:50030");
	let jsoned = cu.to_json().to_string();
	let _ = File::create("lol").ok().unwrap().write_fmt(format_args!("{}", jsoned));
	let decoded = json::decode::<ChatUser>(&jsoned);
	let _ = File::create("kek").ok().unwrap().write_fmt(format_args!("{:?}", decoded));
}
<commit_msg>IT WORKS!!!!!!!!!!!!!!!!!!!!<commit_after>extern crate serde;
extern crate serde_json;

use std::net::{SocketAddr, ToSocketAddrs};
use std::fs::File;
use std::io::Write;
use serde::de::{Error, Type};
use serde_json::value::Value;

#[derive(Debug)]
pub struct ChatUser {
	pub name: String,
	pub poster: SocketAddr,
}

#[derive(Debug)]
pub struct ChatMessage {
	pub sender: ChatUser,
	pub value: String,
}

impl ChatUser {
	//TODO: look it up somewhere, maybe?
	/// Creates a user defined by the supplied arguments
	pub fn get<Addr: ToSocketAddrs>(name: String, poster: Addr) -> ChatUser {
		ChatUser{
			name: name,
			poster: poster.to_socket_addrs().ok().unwrap().next().unwrap(),  //TODO: This should probably be handled, eh?
		}
	}

	pub fn to_json(&self) -> serde_json::Value {
		serde_json::builder::ObjectBuilder::new().insert("name", &self.name).insert("poster", self.poster.to_string()).unwrap()
	}

	pub fn from_json(json: serde_json::Value) -> Result<ChatUser, serde_json::error::Error> {
		match json {
			Value::Object(map) => {
				let name =
					match map.get("name") {
						Some(name) =>
							match name {
								&Value::String(ref name) => name,
								_ => return Err(serde_json::error::Error::type_mismatch(Type::String)),
							},
						None => return Err(serde_json::error::Error::missing_field("Missing \"name\"")),
					};
				let poster =
					match map.get("poster") {
						Some(poster) =>
							match poster {
								&Value::String(ref poster) => poster,
								_ => return Err(serde_json::error::Error::type_mismatch(Type::String)),
							},
						None => return Err(serde_json::error::Error::missing_field("Missing \"poster\"")),
					};

				Ok(ChatUser::get(name.clone(), &poster[..]))
			},
			_ => Err(serde_json::error::Error::type_mismatch(Type::Struct)),
		}
	}
}

#[test]
fn asdf() {
	let cu = ChatUser::get("keke".to_string(), "127.0.0.1:50030");
	let jsoned = serde_json::to_string(&cu.to_json());
	let _ = File::create("lol").ok().unwrap().write_fmt(format_args!("{:?}", jsoned));
	let decoded = ChatUser::from_json(serde_json::from_str(&*&jsoned.ok().unwrap()).ok().unwrap());
	let _ = File::create("kek").ok().unwrap().write_fmt(format_args!("{:?}", decoded));
}
<|endoftext|>