<commit_before>#![allow(missing_docs, nonstandard_style)]

use crate::io::ErrorKind;

#[cfg(any(doc, target_os = "linux"))]
pub use crate::os::linux as platform;

#[cfg(all(not(doc), target_os = "android"))]
pub use crate::os::android as platform;
#[cfg(all(not(doc), target_os = "dragonfly"))]
pub use crate::os::dragonfly as platform;
#[cfg(all(not(doc), target_os = "emscripten"))]
pub use crate::os::emscripten as platform;
#[cfg(all(not(doc), target_os = "freebsd"))]
pub use crate::os::freebsd as platform;
#[cfg(all(not(doc), target_os = "fuchsia"))]
pub use crate::os::fuchsia as platform;
#[cfg(all(not(doc), target_os = "haiku"))]
pub use crate::os::haiku as platform;
#[cfg(all(not(doc), target_os = "illumos"))]
pub use crate::os::illumos as platform;
#[cfg(all(not(doc), target_os = "ios"))]
pub use crate::os::ios as platform;
#[cfg(all(not(doc), target_os = "l4re"))]
pub use crate::os::linux as platform;
#[cfg(all(not(doc), target_os = "macos"))]
pub use crate::os::macos as platform;
#[cfg(all(not(doc), target_os = "netbsd"))]
pub use crate::os::netbsd as platform;
#[cfg(all(not(doc), target_os = "openbsd"))]
pub use crate::os::openbsd as platform;
#[cfg(all(not(doc), target_os = "redox"))]
pub use crate::os::redox as platform;
#[cfg(all(not(doc), target_os = "solaris"))]
pub use crate::os::solaris as platform;

pub use self::rand::hashmap_random_keys;
pub use libc::strlen;

#[macro_use]
pub mod weak;

pub mod alloc;
pub mod android;
pub mod args;
pub mod cmath;
pub mod condvar;
pub mod env;
pub mod ext;
pub mod fd;
pub mod fs;
pub mod io;
#[cfg(target_os = "l4re")]
mod l4re;
pub mod memchr;
pub mod mutex;
#[cfg(not(target_os = "l4re"))]
pub mod net;
#[cfg(target_os = "l4re")]
pub use self::l4re::net;
pub mod os;
pub mod path;
pub mod pipe;
pub mod process;
pub mod rand;
pub mod rwlock;
pub mod stack_overflow;
pub mod stdio;
pub mod thread;
pub mod thread_local_dtor;
pub mod thread_local_key;
pub mod time;

pub use crate::sys_common::os_str_bytes as os_str;

#[cfg(not(test))]
pub fn init() {
    // The standard streams might be closed on application startup. To prevent
    // std::io::{stdin, stdout,stderr} objects from using other unrelated file
    // resources opened later, we reopen standards streams when they are closed.
    unsafe {
        sanitize_standard_fds();
    }

    // By default, some platforms will send a *signal* when an EPIPE error
    // would otherwise be delivered. This runtime doesn't install a SIGPIPE
    // handler, causing it to kill the program, which isn't exactly what we
    // want!
    //
    // Hence, we set SIGPIPE to ignore when the program starts up in order
    // to prevent this problem.
    unsafe {
        reset_sigpipe();
    }

    // In the case when all file descriptors are open, the poll has been
    // observed to perform better than fcntl (on GNU/Linux).
    #[cfg(not(any(
        miri,
        target_os = "emscripten",
        target_os = "fuchsia",
        // The poll on Darwin doesn't set POLLNVAL for closed fds.
        target_os = "macos",
        target_os = "ios",
        target_os = "redox",
    )))]
    unsafe fn sanitize_standard_fds() {
        use crate::sys::os::errno;
        let pfds: &mut [_] = &mut [
            libc::pollfd { fd: 0, events: 0, revents: 0 },
            libc::pollfd { fd: 1, events: 0, revents: 0 },
            libc::pollfd { fd: 2, events: 0, revents: 0 },
        ];
        while libc::poll(pfds.as_mut_ptr(), 3, 0) == -1 {
            if errno() == libc::EINTR {
                continue;
            }
            libc::abort();
        }
        for pfd in pfds {
            if pfd.revents & libc::POLLNVAL == 0 {
                continue;
            }
            if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
                // If the stream is closed but we failed to reopen it, abort the
                // process. Otherwise we wouldn't preserve the safety of
                // operations on the corresponding Rust object Stdin, Stdout, or
                // Stderr.
                libc::abort();
            }
        }
    }
    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "redox"))]
    unsafe fn sanitize_standard_fds() {
        use crate::sys::os::errno;
        for fd in 0..3 {
            if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
                if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
                    libc::abort();
                }
            }
        }
    }
    #[cfg(any(
        // The standard fds are always available in Miri.
        miri,
        target_os = "emscripten",
        target_os = "fuchsia"))]
    unsafe fn sanitize_standard_fds() {}

    #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))]
    unsafe fn reset_sigpipe() {
        assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
    }
    #[cfg(any(target_os = "emscripten", target_os = "fuchsia"))]
    unsafe fn reset_sigpipe() {}
}

#[cfg(target_os = "android")]
pub use crate::sys::android::signal;
#[cfg(not(target_os = "android"))]
pub use libc::signal;

pub fn decode_error_kind(errno: i32) -> ErrorKind {
    match errno as libc::c_int {
        libc::ECONNREFUSED => ErrorKind::ConnectionRefused,
        libc::ECONNRESET => ErrorKind::ConnectionReset,
        libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied,
        libc::EPIPE => ErrorKind::BrokenPipe,
        libc::ENOTCONN => ErrorKind::NotConnected,
        libc::ECONNABORTED => ErrorKind::ConnectionAborted,
        libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
        libc::EADDRINUSE => ErrorKind::AddrInUse,
        libc::ENOENT => ErrorKind::NotFound,
        libc::EINTR => ErrorKind::Interrupted,
        libc::EINVAL => ErrorKind::InvalidInput,
        libc::ETIMEDOUT => ErrorKind::TimedOut,
        libc::EEXIST => ErrorKind::AlreadyExists,

        // These two constants can have the same value on some systems,
        // but different values on others, so we can't use a match
        // clause
        x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => ErrorKind::WouldBlock,

        _ => ErrorKind::Other,
    }
}

#[doc(hidden)]
pub trait IsMinusOne {
    fn is_minus_one(&self) -> bool;
}

macro_rules! impl_is_minus_one {
    ($($t:ident)*) => ($(impl IsMinusOne for $t {
        fn is_minus_one(&self) -> bool {
            *self == -1
        }
    })*)
}

impl_is_minus_one! { i8 i16 i32 i64 isize }

pub fn cvt<T: IsMinusOne>(t: T) -> crate::io::Result<T> {
    if t.is_minus_one() { Err(crate::io::Error::last_os_error()) } else { Ok(t) }
}

pub fn cvt_r<T, F>(mut f: F) -> crate::io::Result<T>
where
    T: IsMinusOne,
    F: FnMut() -> T,
{
    loop {
        match cvt(f()) {
            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
            other => return other,
        }
    }
}

// On Unix-like platforms, libc::abort will unregister signal handlers
// including the SIGABRT handler, preventing the abort from being blocked, and
// fclose streams, with the side effect of flushing them so libc buffered
// output will be printed.  Additionally the shell will generally print a more
// understandable error message like "Abort trap" rather than "Illegal
// instruction" that intrinsics::abort would cause, as intrinsics::abort is
// implemented as an illegal instruction.
pub fn abort_internal() -> ! {
    unsafe { libc::abort() }
}
<commit_msg>Rollup merge of #77288 - RalfJung:miri-macos, r=Amanieu<commit_after>#![allow(missing_docs, nonstandard_style)]

use crate::io::ErrorKind;

#[cfg(any(doc, target_os = "linux"))]
pub use crate::os::linux as platform;

#[cfg(all(not(doc), target_os = "android"))]
pub use crate::os::android as platform;
#[cfg(all(not(doc), target_os = "dragonfly"))]
pub use crate::os::dragonfly as platform;
#[cfg(all(not(doc), target_os = "emscripten"))]
pub use crate::os::emscripten as platform;
#[cfg(all(not(doc), target_os = "freebsd"))]
pub use crate::os::freebsd as platform;
#[cfg(all(not(doc), target_os = "fuchsia"))]
pub use crate::os::fuchsia as platform;
#[cfg(all(not(doc), target_os = "haiku"))]
pub use crate::os::haiku as platform;
#[cfg(all(not(doc), target_os = "illumos"))]
pub use crate::os::illumos as platform;
#[cfg(all(not(doc), target_os = "ios"))]
pub use crate::os::ios as platform;
#[cfg(all(not(doc), target_os = "l4re"))]
pub use crate::os::linux as platform;
#[cfg(all(not(doc), target_os = "macos"))]
pub use crate::os::macos as platform;
#[cfg(all(not(doc), target_os = "netbsd"))]
pub use crate::os::netbsd as platform;
#[cfg(all(not(doc), target_os = "openbsd"))]
pub use crate::os::openbsd as platform;
#[cfg(all(not(doc), target_os = "redox"))]
pub use crate::os::redox as platform;
#[cfg(all(not(doc), target_os = "solaris"))]
pub use crate::os::solaris as platform;

pub use self::rand::hashmap_random_keys;
pub use libc::strlen;

#[macro_use]
pub mod weak;

pub mod alloc;
pub mod android;
pub mod args;
pub mod cmath;
pub mod condvar;
pub mod env;
pub mod ext;
pub mod fd;
pub mod fs;
pub mod io;
#[cfg(target_os = "l4re")]
mod l4re;
pub mod memchr;
pub mod mutex;
#[cfg(not(target_os = "l4re"))]
pub mod net;
#[cfg(target_os = "l4re")]
pub use self::l4re::net;
pub mod os;
pub mod path;
pub mod pipe;
pub mod process;
pub mod rand;
pub mod rwlock;
pub mod stack_overflow;
pub mod stdio;
pub mod thread;
pub mod thread_local_dtor;
pub mod thread_local_key;
pub mod time;

pub use crate::sys_common::os_str_bytes as os_str;

#[cfg(not(test))]
pub fn init() {
    // The standard streams might be closed on application startup. To prevent
    // std::io::{stdin, stdout,stderr} objects from using other unrelated file
    // resources opened later, we reopen standards streams when they are closed.
    unsafe {
        sanitize_standard_fds();
    }

    // By default, some platforms will send a *signal* when an EPIPE error
    // would otherwise be delivered. This runtime doesn't install a SIGPIPE
    // handler, causing it to kill the program, which isn't exactly what we
    // want!
    //
    // Hence, we set SIGPIPE to ignore when the program starts up in order
    // to prevent this problem.
    unsafe {
        reset_sigpipe();
    }

    cfg_if::cfg_if! {
        if #[cfg(miri)] {
            // The standard fds are always available in Miri.
            unsafe fn sanitize_standard_fds() {}
        } else if #[cfg(not(any(
            target_os = "emscripten",
            target_os = "fuchsia",
            // The poll on Darwin doesn't set POLLNVAL for closed fds.
            target_os = "macos",
            target_os = "ios",
            target_os = "redox",
        )))] {
            // In the case when all file descriptors are open, the poll has been
            // observed to perform better than fcntl (on GNU/Linux).
            unsafe fn sanitize_standard_fds() {
                use crate::sys::os::errno;
                let pfds: &mut [_] = &mut [
                    libc::pollfd { fd: 0, events: 0, revents: 0 },
                    libc::pollfd { fd: 1, events: 0, revents: 0 },
                    libc::pollfd { fd: 2, events: 0, revents: 0 },
                ];
                while libc::poll(pfds.as_mut_ptr(), 3, 0) == -1 {
                    if errno() == libc::EINTR {
                        continue;
                    }
                    libc::abort();
                }
                for pfd in pfds {
                    if pfd.revents & libc::POLLNVAL == 0 {
                        continue;
                    }
                    if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
                        // If the stream is closed but we failed to reopen it, abort the
                        // process. Otherwise we wouldn't preserve the safety of
                        // operations on the corresponding Rust object Stdin, Stdout, or
                        // Stderr.
                        libc::abort();
                    }
                }
            }
        } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "redox"))] {
            unsafe fn sanitize_standard_fds() {
                use crate::sys::os::errno;
                for fd in 0..3 {
                    if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
                        if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
                            libc::abort();
                        }
                    }
                }
            }
        } else {
            unsafe fn sanitize_standard_fds() {}
        }
    }

    #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))]
    unsafe fn reset_sigpipe() {
        assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
    }
    #[cfg(any(target_os = "emscripten", target_os = "fuchsia"))]
    unsafe fn reset_sigpipe() {}
}

#[cfg(target_os = "android")]
pub use crate::sys::android::signal;
#[cfg(not(target_os = "android"))]
pub use libc::signal;

pub fn decode_error_kind(errno: i32) -> ErrorKind {
    match errno as libc::c_int {
        libc::ECONNREFUSED => ErrorKind::ConnectionRefused,
        libc::ECONNRESET => ErrorKind::ConnectionReset,
        libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied,
        libc::EPIPE => ErrorKind::BrokenPipe,
        libc::ENOTCONN => ErrorKind::NotConnected,
        libc::ECONNABORTED => ErrorKind::ConnectionAborted,
        libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
        libc::EADDRINUSE => ErrorKind::AddrInUse,
        libc::ENOENT => ErrorKind::NotFound,
        libc::EINTR => ErrorKind::Interrupted,
        libc::EINVAL => ErrorKind::InvalidInput,
        libc::ETIMEDOUT => ErrorKind::TimedOut,
        libc::EEXIST => ErrorKind::AlreadyExists,

        // These two constants can have the same value on some systems,
        // but different values on others, so we can't use a match
        // clause
        x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => ErrorKind::WouldBlock,

        _ => ErrorKind::Other,
    }
}

#[doc(hidden)]
pub trait IsMinusOne {
    fn is_minus_one(&self) -> bool;
}

macro_rules! impl_is_minus_one {
    ($($t:ident)*) => ($(impl IsMinusOne for $t {
        fn is_minus_one(&self) -> bool {
            *self == -1
        }
    })*)
}

impl_is_minus_one! { i8 i16 i32 i64 isize }

pub fn cvt<T: IsMinusOne>(t: T) -> crate::io::Result<T> {
    if t.is_minus_one() { Err(crate::io::Error::last_os_error()) } else { Ok(t) }
}

pub fn cvt_r<T, F>(mut f: F) -> crate::io::Result<T>
where
    T: IsMinusOne,
    F: FnMut() -> T,
{
    loop {
        match cvt(f()) {
            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
            other => return other,
        }
    }
}

// On Unix-like platforms, libc::abort will unregister signal handlers
// including the SIGABRT handler, preventing the abort from being blocked, and
// fclose streams, with the side effect of flushing them so libc buffered
// output will be printed.  Additionally the shell will generally print a more
// understandable error message like "Abort trap" rather than "Illegal
// instruction" that intrinsics::abort would cause, as intrinsics::abort is
// implemented as an illegal instruction.
pub fn abort_internal() -> ! {
    unsafe { libc::abort() }
}
<|endoftext|>


<commit_before><commit_msg>Remoive unused 'use'<commit_after><|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/*!
# Rust-PortAudio

__Portaudio__ bindings for Rust

PortAudio provides a uniform application programming interface (API) across all
supported platforms.  You can think of the PortAudio library as a wrapper that
converts calls to the PortAudio API into calls to platform-specific native audio
APIs. Operating systems often offer more than one native audio API and some APIs
(such as JACK) may be available on multiple target operating systems.
PortAudio supports all the major native audio APIs on each supported platform.

# Installation

You must install on your computer the Portaudio libraries who is used for
the binding.

Portaudio is available with package management tools on Linux, or brew on Mac OS.

You can download it directly from the website :
[portaudio](http://www.portaudio.com/download.html)

Then clone the repo and build the library with the following command at the root
of the __rust-portaudio__ repository.

__rust-portaudio__ is build with the rustpkg tool :

```Shell
> rustpkg build portaudio
```

*/

#![crate_id = "portaudio#0.1"]

#![comment = "Portaudio binding for Rust"]
#![license = "MIT"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]

#![feature(globs)]
#![warn(missing_doc)]
#![allow(dead_code)]
#![allow(visible_private_types)]
#![allow(deprecated_owned_vector)]

extern crate libc;

#[cfg(target_os="macos")]
#[cfg(target_os="linux")]
#[cfg(target_os="win32")]
mod c_library {
    #[link(name = "portaudio")]
    extern {}
}

pub mod types;
pub mod pa;

//#[doc(hidden)]
//pub mod user_traits;
//#[doc(hidden)]
//#[cfg(target_os="macos")]
//pub mod mac_core;
//pub mod asio;
#[doc(hidden)]
mod ffi;
<commit_msg>remove warning<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/*!
# Rust-PortAudio

__Portaudio__ bindings for Rust

PortAudio provides a uniform application programming interface (API) across all
supported platforms.  You can think of the PortAudio library as a wrapper that
converts calls to the PortAudio API into calls to platform-specific native audio
APIs. Operating systems often offer more than one native audio API and some APIs
(such as JACK) may be available on multiple target operating systems.
PortAudio supports all the major native audio APIs on each supported platform.

# Installation

You must install on your computer the Portaudio libraries who is used for
the binding.

Portaudio is available with package management tools on Linux, or brew on Mac OS.

You can download it directly from the website :
[portaudio](http://www.portaudio.com/download.html)

Then clone the repo and build the library with the following command at the root
of the __rust-portaudio__ repository.

__rust-portaudio__ is build with the rustpkg tool :

```Shell
> rustpkg build portaudio
```

*/

#![crate_id = "portaudio#0.1"]

#![comment = "Portaudio binding for Rust"]
#![license = "MIT"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]

#![feature(globs)]
#![warn(missing_doc)]
#![allow(dead_code)]
#![allow(visible_private_types)]

extern crate libc;

#[cfg(target_os="macos")]
#[cfg(target_os="linux")]
#[cfg(target_os="win32")]
mod c_library {
    #[link(name = "portaudio")]
    extern {}
}

pub mod types;
pub mod pa;

//#[doc(hidden)]
//pub mod user_traits;
//#[doc(hidden)]
//#[cfg(target_os="macos")]
//pub mod mac_core;
//pub mod asio;
#[doc(hidden)]
mod ffi;
<|endoftext|>


<commit_before>// Copyright (c) 2013-2017 Sandstorm Development Group, Inc. and contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::cell::{Cell, RefCell};
use std::slice;
use std::u64;

use private::units::*;
use message;
use message::{Allocator, ReaderSegments};
use {Error, OutputSegments, Result, Word};

pub type SegmentId = u32;

pub struct ReadLimiter {
    pub limit: Cell<u64>,
}

impl ReadLimiter {
    pub fn new(limit: u64) -> ReadLimiter {
        ReadLimiter { limit: Cell::new(limit) }
    }

    #[inline]
    pub fn can_read(&self, amount: u64) -> Result<()> {
        let current = self.limit.get();
        if amount > current {
            Err(Error::failed(format!("read limit exceeded")))
        } else {
            self.limit.set(current - amount);
            Ok(())
        }
    }
}

pub trait ReaderArena {
    fn get_segment(&self, id: u32) -> Result<(*const Word, u32)>;
    fn contains_interval(&self, segment_id: u32, start: *const Word, size: usize) -> Result<()>;
    fn amplified_read(&self, virtual_amount: u64) -> Result<()>;

    // TODO(version 0.9): Consider putting extract_cap(), inject_cap(), drop_cap() here
    //   and on message::Reader. Then we could get rid of Imbue and ImbueMut, and
    //   layout::StructReader, layout::ListReader, etc. could drop their `cap_table` fields.
}

pub struct ReaderArenaImpl<S> {
    segments: S,
    read_limiter: ReadLimiter,
}

impl <S> ReaderArenaImpl <S> where S: ReaderSegments {
    pub fn new(segments: S,
               options: message::ReaderOptions)
               -> Self
    {
        let limiter = ReadLimiter::new(options.traversal_limit_in_words);
        ReaderArenaImpl {
            segments: segments,
            read_limiter: limiter,
        }
    }

    pub fn into_segments(self) -> S {
        self.segments
    }
}

impl <S> ReaderArena for ReaderArenaImpl<S> where S: ReaderSegments {
    fn get_segment<'a>(&'a self, id: u32) -> Result<(*const Word, u32)> {
        match self.segments.get_segment(id) {
            Some(seg) => Ok((seg.as_ptr(), seg.len() as u32)),
            None => Err(Error::failed(format!("Invalid segment id: {}", id))),
        }
    }

    fn contains_interval(&self, id: u32, start: *const Word, size_in_words: usize) -> Result<()> {
        let (segment_start, segment_len) = try!(self.get_segment(id));
        let this_start: usize = segment_start as usize;
        let this_size: usize = segment_len as usize * 8;
        let start_usize = start as usize;
        let size = size_in_words * BYTES_PER_WORD;

        if !(start_usize >= this_start && start_usize - this_start + size <= this_size) {
            Err(Error::failed(format!("message contained out-of-bounds pointer")))
        } else {
            self.read_limiter.can_read(size_in_words as u64)
        }
    }

    fn amplified_read(&self, virtual_amount: u64) -> Result<()> {
        self.read_limiter.can_read(virtual_amount)
    }
}

pub trait BuilderArena: ReaderArena {
    // These methods all take an immutable &self because otherwise a StructBuilder<'a>
    // would need a `&'a mut BuilderArena` and `StructBuilder::borrow()` would
    // have lifetime issues. (If `'a: 'b`, then a `&'a (BuilderArena + 'a)` can be
    // converted to a `&'b (BuilderArena + 'b)`, but a `&'a mut (BuilderArena + 'a)`
    // *cannot* be converted to a `&'b (BuilderArena + 'b)`. See some discussion here:
    // https://botbot.me/mozilla/rust/2017-01-31/?msg=80228117&page=19 .)
    fn allocate(&self, segment_id: u32, amount: WordCount32) -> Option<u32>;
    fn allocate_anywhere(&self, amount: u32) -> (SegmentId, u32);
    fn get_segment_mut(&self, id: u32) -> (*mut Word, u32);
    fn as_reader<'a>(&'a self) -> &'a ReaderArena;
}

pub struct BuilderArenaImplInner<A> where A: Allocator {
    allocator: A,

    // TODO(perf): Try using smallvec to avoid heap allocations in the single-segment case?
    segments: Vec<(*mut Word, u32)>,
    allocated: Vec<u32>, // number of words allocated for each segment.
}

pub struct BuilderArenaImpl<A> where A: Allocator {
    inner: RefCell<BuilderArenaImplInner<A>>
}

impl <A> BuilderArenaImpl<A> where A: Allocator {
    pub fn new(allocator: A) -> Self {
        BuilderArenaImpl {
            inner: RefCell::new(BuilderArenaImplInner {
                allocator: allocator,
                segments: Vec::new(),
                allocated: Vec::new(),
            }),
        }
    }

    pub fn allocate_segment(&self, minimum_size: u32) -> Result<()> {
        self.inner.borrow_mut().allocate_segment(minimum_size)
    }

    pub fn get_segments_for_output<'a>(&'a self) -> OutputSegments<'a> {
        let reff = self.inner.borrow();
        if reff.allocated.len() == 1 {
            let seg = reff.segments[0];

            // The user must mutably borrow the `message::Builder` to be able to modify segment memory.
            // No such borrow will be possible while `self` is still immutably borrowed from this method,
            // so returning this slice is safe.
            let slice = unsafe { slice::from_raw_parts(seg.0 as *const _, reff.allocated[0] as usize) };
            OutputSegments::SingleSegment([slice])
        } else {
            let mut v = Vec::with_capacity(reff.allocated.len());
            for idx in 0..reff.allocated.len() {
                let seg = reff.segments[idx];

                // See safety argument in above branch.
                let slice = unsafe { slice::from_raw_parts(seg.0 as *const _, reff.allocated[idx] as usize) };
                v.push(slice);
            }
            OutputSegments::MultiSegment(v)
        }
    }

    pub fn len(&self) -> usize {
        self.inner.borrow().allocated.len()
    }
}

impl <A> ReaderArena for BuilderArenaImpl<A> where A: Allocator {
    fn get_segment(&self, id: u32) -> Result<(*const Word, u32)> {
        let borrow = self.inner.borrow();
        let seg = borrow.segments[id as usize];
        Ok((seg.0 as *const _, seg.1))
    }

    fn contains_interval(&self, _id: u32, _start: *const Word, _size: usize) -> Result<()> {
        Ok(())
    }

    fn amplified_read(&self, _virtual_amount: u64) -> Result<()> {
        Ok(())
    }
}

impl <A> BuilderArenaImplInner<A> where A: Allocator {
    fn allocate_segment(&mut self, minimum_size: WordCount32) -> Result<()> {
        let seg = self.allocator.allocate_segment(minimum_size);
        self.segments.push(seg);
        self.allocated.push(0);
        Ok(())
    }

    fn allocate(&mut self, segment_id: u32, amount: WordCount32) -> Option<u32> {
        if amount > self.get_segment_mut(segment_id).1 as u32 - self.allocated[segment_id as usize] {
            None
        } else {
            let result = self.allocated[segment_id as usize];
            self.allocated[segment_id as usize] += amount;
            Some(result)
        }
    }

    fn allocate_anywhere(&mut self, amount: u32) -> (SegmentId, u32) {
        // first try the existing segments, then try allocating a new segment.
        let allocated_len = self.allocated.len() as u32;
        for segment_id in 0.. allocated_len {
            match self.allocate(segment_id, amount) {
                Some(idx) => return (segment_id, idx),
                None => (),
            }
        }

        // Need to allocate a new segment.

        self.allocate_segment(amount).expect("allocate new segment");
        (allocated_len,
         self.allocate(allocated_len, amount).expect("use freshly-allocated segment"))
    }

    fn get_segment_mut(&mut self, id: u32) -> (*mut Word, u32) {
        self.segments[id as usize]
    }

}

impl <A> BuilderArena for BuilderArenaImpl<A> where A: Allocator {
    fn allocate(&self, segment_id: u32, amount: WordCount32) -> Option<u32> {
        self.inner.borrow_mut().allocate(segment_id, amount)
    }

    fn allocate_anywhere(&self, amount: u32) -> (SegmentId, u32) {
        self.inner.borrow_mut().allocate_anywhere(amount)
    }

    fn get_segment_mut(&self, id: u32) -> (*mut Word, u32) {
        self.inner.borrow_mut().get_segment_mut(id)
    }

    fn as_reader<'a>(&'a self) -> &'a ReaderArena {
        self
    }
}

impl <A> Drop for BuilderArenaImplInner<A> where A: Allocator {
    fn drop(&mut self) {
        if self.allocated.len() > 0 {
            self.allocator.pre_drop(self.allocated[0]);
        }
    }
}

pub struct NullArena;

impl ReaderArena for NullArena {
    fn get_segment(&self, _id: u32) -> Result<(*const Word, u32)> {
        Err(Error::failed(format!("tried to read from null arena")))
    }

    fn contains_interval(&self, _id: u32, _start: *const Word, _size: usize) -> Result<()> {
        Ok(())
    }

    fn amplified_read(&self, _virtual_amount: u64) -> Result<()> {
        Ok(())
    }
}

impl BuilderArena for NullArena {
    fn allocate(&self, _segment_id: u32, _amount: WordCount32) -> Option<u32> {
        None
    }

    fn allocate_anywhere(&self, _amount: u32) -> (SegmentId, u32) {
        panic!("tried to allocate from a null arena")
    }

    fn get_segment_mut(&self, _id: u32) -> (*mut Word, u32) {
        (::std::ptr::null_mut(), 0)
    }

    fn as_reader<'a>(&'a self) -> &'a ReaderArena {
        self
    }
}

<commit_msg>minor cleanup<commit_after>// Copyright (c) 2013-2017 Sandstorm Development Group, Inc. and contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::cell::{Cell, RefCell};
use std::slice;
use std::u64;

use private::units::*;
use message;
use message::{Allocator, ReaderSegments};
use {Error, OutputSegments, Result, Word};

pub type SegmentId = u32;

pub struct ReadLimiter {
    pub limit: Cell<u64>,
}

impl ReadLimiter {
    pub fn new(limit: u64) -> ReadLimiter {
        ReadLimiter { limit: Cell::new(limit) }
    }

    #[inline]
    pub fn can_read(&self, amount: u64) -> Result<()> {
        let current = self.limit.get();
        if amount > current {
            Err(Error::failed(format!("read limit exceeded")))
        } else {
            self.limit.set(current - amount);
            Ok(())
        }
    }
}

pub trait ReaderArena {
    fn get_segment(&self, id: u32) -> Result<(*const Word, u32)>;
    fn contains_interval(&self, segment_id: u32, start: *const Word, size: usize) -> Result<()>;
    fn amplified_read(&self, virtual_amount: u64) -> Result<()>;

    // TODO(version 0.9): Consider putting extract_cap(), inject_cap(), drop_cap() here
    //   and on message::Reader. Then we could get rid of Imbue and ImbueMut, and
    //   layout::StructReader, layout::ListReader, etc. could drop their `cap_table` fields.
}

pub struct ReaderArenaImpl<S> {
    segments: S,
    read_limiter: ReadLimiter,
}

impl <S> ReaderArenaImpl <S> where S: ReaderSegments {
    pub fn new(segments: S,
               options: message::ReaderOptions)
               -> Self
    {
        let limiter = ReadLimiter::new(options.traversal_limit_in_words);
        ReaderArenaImpl {
            segments: segments,
            read_limiter: limiter,
        }
    }

    pub fn into_segments(self) -> S {
        self.segments
    }
}

impl <S> ReaderArena for ReaderArenaImpl<S> where S: ReaderSegments {
    fn get_segment<'a>(&'a self, id: u32) -> Result<(*const Word, u32)> {
        match self.segments.get_segment(id) {
            Some(seg) => Ok((seg.as_ptr(), seg.len() as u32)),
            None => Err(Error::failed(format!("Invalid segment id: {}", id))),
        }
    }

    fn contains_interval(&self, id: u32, start: *const Word, size_in_words: usize) -> Result<()> {
        let (segment_start, segment_len) = try!(self.get_segment(id));
        let this_start: usize = segment_start as usize;
        let this_size: usize = segment_len as usize * BYTES_PER_WORD;
        let start = start as usize;
        let size = size_in_words * BYTES_PER_WORD;

        if !(start >= this_start && start - this_start + size <= this_size) {
            Err(Error::failed(format!("message contained out-of-bounds pointer")))
        } else {
            self.read_limiter.can_read(size_in_words as u64)
        }
    }

    fn amplified_read(&self, virtual_amount: u64) -> Result<()> {
        self.read_limiter.can_read(virtual_amount)
    }
}

pub trait BuilderArena: ReaderArena {
    // These methods all take an immutable &self because otherwise a StructBuilder<'a>
    // would need a `&'a mut BuilderArena` and `StructBuilder::borrow()` would
    // have lifetime issues. (If `'a: 'b`, then a `&'a (BuilderArena + 'a)` can be
    // converted to a `&'b (BuilderArena + 'b)`, but a `&'a mut (BuilderArena + 'a)`
    // *cannot* be converted to a `&'b (BuilderArena + 'b)`. See some discussion here:
    // https://botbot.me/mozilla/rust/2017-01-31/?msg=80228117&page=19 .)
    fn allocate(&self, segment_id: u32, amount: WordCount32) -> Option<u32>;
    fn allocate_anywhere(&self, amount: u32) -> (SegmentId, u32);
    fn get_segment_mut(&self, id: u32) -> (*mut Word, u32);
    fn as_reader<'a>(&'a self) -> &'a ReaderArena;
}

pub struct BuilderArenaImplInner<A> where A: Allocator {
    allocator: A,

    // TODO(perf): Try using smallvec to avoid heap allocations in the single-segment case?
    segments: Vec<(*mut Word, u32)>,
    allocated: Vec<u32>, // number of words allocated for each segment.
}

pub struct BuilderArenaImpl<A> where A: Allocator {
    inner: RefCell<BuilderArenaImplInner<A>>
}

impl <A> BuilderArenaImpl<A> where A: Allocator {
    pub fn new(allocator: A) -> Self {
        BuilderArenaImpl {
            inner: RefCell::new(BuilderArenaImplInner {
                allocator: allocator,
                segments: Vec::new(),
                allocated: Vec::new(),
            }),
        }
    }

    pub fn allocate_segment(&self, minimum_size: u32) -> Result<()> {
        self.inner.borrow_mut().allocate_segment(minimum_size)
    }

    pub fn get_segments_for_output<'a>(&'a self) -> OutputSegments<'a> {
        let reff = self.inner.borrow();
        if reff.allocated.len() == 1 {
            let seg = reff.segments[0];

            // The user must mutably borrow the `message::Builder` to be able to modify segment memory.
            // No such borrow will be possible while `self` is still immutably borrowed from this method,
            // so returning this slice is safe.
            let slice = unsafe { slice::from_raw_parts(seg.0 as *const _, reff.allocated[0] as usize) };
            OutputSegments::SingleSegment([slice])
        } else {
            let mut v = Vec::with_capacity(reff.allocated.len());
            for idx in 0..reff.allocated.len() {
                let seg = reff.segments[idx];

                // See safety argument in above branch.
                let slice = unsafe { slice::from_raw_parts(seg.0 as *const _, reff.allocated[idx] as usize) };
                v.push(slice);
            }
            OutputSegments::MultiSegment(v)
        }
    }

    pub fn len(&self) -> usize {
        self.inner.borrow().allocated.len()
    }
}

impl <A> ReaderArena for BuilderArenaImpl<A> where A: Allocator {
    fn get_segment(&self, id: u32) -> Result<(*const Word, u32)> {
        let borrow = self.inner.borrow();
        let seg = borrow.segments[id as usize];
        Ok((seg.0 as *const _, seg.1))
    }

    fn contains_interval(&self, _id: u32, _start: *const Word, _size: usize) -> Result<()> {
        Ok(())
    }

    fn amplified_read(&self, _virtual_amount: u64) -> Result<()> {
        Ok(())
    }
}

impl <A> BuilderArenaImplInner<A> where A: Allocator {
    fn allocate_segment(&mut self, minimum_size: WordCount32) -> Result<()> {
        let seg = self.allocator.allocate_segment(minimum_size);
        self.segments.push(seg);
        self.allocated.push(0);
        Ok(())
    }

    fn allocate(&mut self, segment_id: u32, amount: WordCount32) -> Option<u32> {
        if amount > self.get_segment_mut(segment_id).1 as u32 - self.allocated[segment_id as usize] {
            None
        } else {
            let result = self.allocated[segment_id as usize];
            self.allocated[segment_id as usize] += amount;
            Some(result)
        }
    }

    fn allocate_anywhere(&mut self, amount: u32) -> (SegmentId, u32) {
        // first try the existing segments, then try allocating a new segment.
        let allocated_len = self.allocated.len() as u32;
        for segment_id in 0.. allocated_len {
            match self.allocate(segment_id, amount) {
                Some(idx) => return (segment_id, idx),
                None => (),
            }
        }

        // Need to allocate a new segment.

        self.allocate_segment(amount).expect("allocate new segment");
        (allocated_len,
         self.allocate(allocated_len, amount).expect("use freshly-allocated segment"))
    }

    fn get_segment_mut(&mut self, id: u32) -> (*mut Word, u32) {
        self.segments[id as usize]
    }

}

impl <A> BuilderArena for BuilderArenaImpl<A> where A: Allocator {
    fn allocate(&self, segment_id: u32, amount: WordCount32) -> Option<u32> {
        self.inner.borrow_mut().allocate(segment_id, amount)
    }

    fn allocate_anywhere(&self, amount: u32) -> (SegmentId, u32) {
        self.inner.borrow_mut().allocate_anywhere(amount)
    }

    fn get_segment_mut(&self, id: u32) -> (*mut Word, u32) {
        self.inner.borrow_mut().get_segment_mut(id)
    }

    fn as_reader<'a>(&'a self) -> &'a ReaderArena {
        self
    }
}

impl <A> Drop for BuilderArenaImplInner<A> where A: Allocator {
    fn drop(&mut self) {
        if self.allocated.len() > 0 {
            self.allocator.pre_drop(self.allocated[0]);
        }
    }
}

pub struct NullArena;

impl ReaderArena for NullArena {
    fn get_segment(&self, _id: u32) -> Result<(*const Word, u32)> {
        Err(Error::failed(format!("tried to read from null arena")))
    }

    fn contains_interval(&self, _id: u32, _start: *const Word, _size: usize) -> Result<()> {
        Ok(())
    }

    fn amplified_read(&self, _virtual_amount: u64) -> Result<()> {
        Ok(())
    }
}

impl BuilderArena for NullArena {
    fn allocate(&self, _segment_id: u32, _amount: WordCount32) -> Option<u32> {
        None
    }

    fn allocate_anywhere(&self, _amount: u32) -> (SegmentId, u32) {
        panic!("tried to allocate from a null arena")
    }

    fn get_segment_mut(&self, _id: u32) -> (*mut Word, u32) {
        (::std::ptr::null_mut(), 0)
    }

    fn as_reader<'a>(&'a self) -> &'a ReaderArena {
        self
    }
}

<|endoftext|>


<commit_before>use std::f64::INFINITY;
use raytracer::Intersection;
use scene::Scene;
use vec3::Vec3;

pub struct Ray {
    pub origin: Vec3,
    pub direction: Vec3,
    pub inverse_dir: Vec3 // This is used to optimise ray-bbox intersection checks
}

impl Ray {
    pub fn new(origin: Vec3, direction: Vec3) -> Ray {
        Ray {
            origin: origin,
            direction: direction,
            inverse_dir: Vec3 {
                x: 1.0 / direction.x,
                y: 1.0 / direction.y,
                z: 1.0 / direction.z
            }
        }
    }

    pub fn get_nearest_hit<'a>(&'a self, scene: &'a Scene) -> Option<Intersection<'a>> {
        let t_min = 0.000001;
        let mut nearest_hit = None;
        let mut nearest_t = INFINITY;

        let candidate_nodes = scene.prim_strat.get_intersection_objects(self);

        for prim in candidate_nodes.iter() {
            let intersection = prim.intersects(self, t_min, nearest_t);

            nearest_hit = match intersection {
                Some(intersection) => {
                    if intersection.t > t_min && intersection.t < nearest_t {
                        nearest_t = intersection.t;
                        Some(intersection)
                    } else {
                        nearest_hit
                    }
                }
                None => {nearest_hit}
            };
        }

        nearest_hit
    }
}
<commit_msg>Add test to Ray<commit_after>use std::f64::INFINITY;
use raytracer::Intersection;
use scene::Scene;
use vec3::Vec3;

#[cfg(test)]
use geometry::prim::Prim;
#[cfg(test)]
use geometry::prims::Sphere;
#[cfg(test)]
use light::light::Light;
#[cfg(test)]
use material::materials::FlatMaterial;
#[cfg(test)]
use raytracer::VecPrimContainer;

pub struct Ray {
    pub origin: Vec3,
    pub direction: Vec3,
    pub inverse_dir: Vec3 // This is used to optimise ray-bbox intersection checks
}

impl Ray {
    pub fn new(origin: Vec3, direction: Vec3) -> Ray {
        Ray {
            origin: origin,
            direction: direction,
            inverse_dir: Vec3 {
                x: 1.0 / direction.x,
                y: 1.0 / direction.y,
                z: 1.0 / direction.z
            }
        }
    }

    pub fn get_nearest_hit<'a>(&'a self, scene: &'a Scene) -> Option<Intersection<'a>> {
        let t_min = 0.000001;
        let mut nearest_hit = None;
        let mut nearest_t = INFINITY;

        let candidate_nodes = scene.prim_strat.get_intersection_objects(self);

        for prim in candidate_nodes.iter() {
            let intersection = prim.intersects(self, t_min, nearest_t);

            nearest_hit = match intersection {
                Some(intersection) => {
                    if intersection.t > t_min && intersection.t < nearest_t {
                        nearest_t = intersection.t;
                        Some(intersection)
                    } else {
                        nearest_hit
                    }
                },
                None => nearest_hit
            };
        }

        nearest_hit
    }
}

#[test]
fn it_gets_the_nearest_hit() {
    let mut lights: Vec<Box<Light+Send+Share>> = Vec::new();

    let mut prims: Vec<Box<Prim+Send+Share>> = Vec::new();
    let mat = FlatMaterial { color: Vec3::one() };
    let sphere_top = Sphere {
        center: Vec3::zero(),
        radius: 1.0,
        material: box mat.clone()
    };
    let sphere_mid = Sphere {
        center: Vec3 { x: -1.0, y: 0.0, z: 0.0 },
        radius: 1.0,
        material: box mat.clone()
    };
    let sphere_bot = Sphere {
        center: Vec3 { x: -2.0, y: 0.0, z: 0.0 },
        radius: 1.0,
        material: box mat.clone()
    };
    prims.push(box sphere_top);
    prims.push(box sphere_mid);
    prims.push(box sphere_bot);

    let scene = Scene {
        lights: lights,
        background: Vec3::one(),
        prim_strat: box VecPrimContainer::new(prims),
        skybox: None
    };

    let intersecting_ray = Ray::new(
        Vec3 { x: 10.0, y: 0.0, z: 0.0 },
        Vec3 { x: -1.0, y: 0.0, z: 0.0 }
    );

    let intersection = intersecting_ray.get_nearest_hit(&scene);
    assert_eq!(1.0, intersection.unwrap().position.x);

    let non_intersecting_ray = Ray::new(
        Vec3 { x: 10.0, y: 0.0, z: 0.0 },
        Vec3 { x: 1.0, y: 0.0, z: 0.0 });

    let non_intersection = non_intersecting_ray.get_nearest_hit(&scene);
    assert!(non_intersection.is_none());
}
<|endoftext|>


<commit_before>use std::thread;
use std::sync::{Arc, Mutex};
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};
use std::collections::HashMap;
use consts::{WatchedEventType, ZkError, ZkState};
use proto::WatchedEvent;
use zookeeper::{ZkResult, ZooKeeper};
use zookeeper_ext::ZooKeeperExt;
use listeners::{ListenerSet, Subscription};

pub type ChildData = Arc<Vec<u8>>;
pub type Data = HashMap<String, ChildData>;

#[derive(Debug,Clone)]
pub enum PathChildrenCacheEvent {
    Initialized,
    ConnectionSuspended,
    ConnectionLost,
    ConnectionReconnected,
    ChildRemoved(String),
    ChildAdded(String, ChildData),
    ChildUpdated(String, ChildData),
}

#[derive(Debug)]
pub enum RefreshMode {
    Standard,
    ForceGetDataAndStat,
}

#[derive(Debug)]
pub enum Operation {
    Shutdown,
    Refresh(RefreshMode),
    Event(PathChildrenCacheEvent),
    GetData(String /* path */),
}

pub struct PathChildrenCache {
    path: Arc<String>,
    zk: Arc<ZooKeeper>,
    data: Arc<Mutex<Data>>,
    worker_thread: Option<thread::JoinHandle<()>>,
    channel: Option<Sender<Operation>>,
    listener_subscription: Option<Subscription>,
    event_listeners: ListenerSet<PathChildrenCacheEvent>,
}

impl PathChildrenCache {

    fn get_children(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>, ops_chan: Sender<Operation>) -> ZkResult<()> {
        let ops_chan1 = ops_chan.clone();

        let watcher = move |event: &WatchedEvent| {
            match event.event_type {
                WatchedEventType::NodeChildrenChanged => {
                    let _path = event.path.as_ref().expect("Path absent");

                    // Subscribe to new changes recursively
                    match ops_chan1.send(Operation::Refresh(RefreshMode::Standard)) {
                        Err(err) => {
                            warn!("error sending Refresh operation to ops channel: {:?}", err);
                        },
                        _ => {}
                    };
                },
                _ => error!("Unexpected: {:?}", event)
            };
        };

        let children = try!(zk.get_children_w(&path, watcher));

        let mut data_locked = data.lock().unwrap();

        for child in children.iter() {
            let child_path = join_path(path, child);

            if !data_locked.contains_key(&child_path) {

                let child_data = try!(Self::get_data(zk.clone(), &child_path, data.clone(), ops_chan.clone()));

                let child_data = Arc::new(child_data);

                data_locked.insert(child_path.clone(), child_data.clone());

                try!(ops_chan.send(Operation::Event(PathChildrenCacheEvent::ChildAdded(child_path, child_data))).map_err(|err| {
                    info!("error sending ChildAdded event: {:?}", err);
                    ZkError::APIError
                }));
            }
        }

        debug!("New data: {:?}", *data_locked);

        Ok(())
    }

    fn get_data(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>, ops_chan: Sender<Operation>) -> ZkResult<Vec<u8>> {
        let path1 = path.to_owned();

        let data_watcher = move |event: &WatchedEvent| {
            let mut data_locked = data.lock().unwrap();
            match event.event_type {
                WatchedEventType::NodeDeleted => {
                    data_locked.remove(&path1);

                    match ops_chan.send(Operation::Event(PathChildrenCacheEvent::ChildRemoved(path1.clone()))) {
                        Err(err) => {
                            warn!("error sending ChildRemoved event: {:?}", err);
                        },
                        _ => {}
                    }
                },
                WatchedEventType::NodeDataChanged => {
                    // Subscribe to new changes recursively
                    match ops_chan.send(Operation::GetData(path1)) {
                        Err(err) => {
                            warn!("error sending GetData to op channel: {:?}", err);
                        },
                        _ => {}
                    }
                },
                _ => error!("Unexpected: {:?}", event)
            };

            debug!("New data: {:?}", *data_locked);
        };

        zk.get_data_w(path, data_watcher).map(|stuff| { stuff.0 })
    }

    fn update_data(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>, ops_chan_tx: Sender<Operation>) -> ZkResult<()> {
        let mut data_locked = data.lock().unwrap();

        let path = path.to_owned();

        let result = Self::get_data(zk.clone(), &path, data.clone(), ops_chan_tx.clone());

        match result {
            Ok(child_data) => {
                info!("got data {:?}", child_data);

                let child_data = Arc::new(child_data);

                data_locked.insert(path.clone(), child_data.clone());

                ops_chan_tx.send(Operation::Event(PathChildrenCacheEvent::ChildUpdated(path, child_data))).map_err(|err| {
                    warn!("error sending ChildUpdated event: {:?}", err);
                    ZkError::APIError
                })
            },
            Err(err) => {
                warn!("error getting child data: {:?}", err);
                Err(ZkError::APIError)
            }
        }
    }

    pub fn new(zk: Arc<ZooKeeper>, path: &str) -> ZkResult<PathChildrenCache> {

        let data = Arc::new(Mutex::new(HashMap::new()));

        try!(zk.ensure_path(path));

        Ok(PathChildrenCache{
            path: Arc::new(path.to_string()),
            zk: zk,
            data: data,
            worker_thread: None,
            channel: None,
            listener_subscription: None,
            event_listeners: ListenerSet::new(),
        })
    }

    pub fn get_current_data(&self) -> Data {
        self.data.lock().unwrap().clone()
    }

    pub fn clear(&self) {
        self.data.lock().unwrap().clear()
    }

    fn handle_state_change(state: ZkState, ops_chan_tx: Sender<Operation>) -> bool {
        let mut done = false;

        info!("zk state change {:?}", state);
        match state {
            ZkState::Connected => {
                match ops_chan_tx.send(Operation::Refresh(RefreshMode::ForceGetDataAndStat)) {
                    Err(err) => {
                        warn!("error sending Refresh to op channel: {:?}", err);
                        done = true;
                    },
                    _ => {}
                }
            },
            _ => {
            }
        }

        done
    }

    fn handle_operation(op: Operation, zk: Arc<ZooKeeper>, path: Arc<String>, data: Arc<Mutex<Data>>, event_listeners: ListenerSet<PathChildrenCacheEvent>, ops_chan_tx: Sender<Operation>) -> bool {
        let mut done = false;

        debug!("handling op {:?}", op);
        match op {
            Operation::Shutdown => {
                info!("shutting down worker thread");
                done = true;
            },
            Operation::Refresh(_mode) => {
                debug!("getting children");
                let result = Self::get_children(zk.clone(), &*path, data.clone(), ops_chan_tx.clone());
                info!("got children {:?}", result);
            },
            Operation::GetData(path) => {
                debug!("getting data");
                let result = Self::update_data(zk.clone(), &*path, data.clone(), ops_chan_tx.clone());
                match result {
                    Err(err) => {
                        warn!("error getting child data: {:?}", err);
                    },
                    _ => {}
                }
            },
            Operation::Event(event) => {
                info!("received event {:?}", event);
                event_listeners.notify(&event);
            },
        }

        done
    }

    pub fn start(&mut self) -> ZkResult<()> {
        let (ops_chan_tx, ops_chan_rx) = mpsc::channel();
        let (listener_chan_tx, listener_chan_rx) = mpsc::channel();

        let sub = self.zk.add_listener(listener_chan_tx.clone());
        self.listener_subscription = Some(sub);

        let zk = self.zk.clone();
        let path = self.path.clone();
        let data = self.data.clone();
        let event_listeners = self.event_listeners.clone();
        self.channel = Some(ops_chan_tx.clone());

        self.worker_thread = Some(thread::spawn(move || {
            let mut done = false;

            while !done {
                select! (
                    state_result = listener_chan_rx.recv() => {
                        match state_result {
                            Ok(state) => {
                                done = Self::handle_state_change(state, ops_chan_tx.clone());
                            },
                            Err(err) => {
                                info!("zk state chan err. shutting down. {:?}", err);
                                done = true;
                            }
                        }
                    },
                    op_result = ops_chan_rx.recv() => {
                        match op_result {
                            Ok(operation) => {
                                done = Self::handle_operation(operation, zk.clone(), path.clone(), data.clone(), event_listeners.clone(), ops_chan_tx.clone());
                            },
                            Err(err) => {
                                info!("error receiving from operations channel ({:?}). shutting down worker thread", err);
                                done = true;
                            }
                        }
                    });
            }
        }));

        self.offer_operation(Operation::Refresh(RefreshMode::ForceGetDataAndStat))
    }

    pub fn add_listener(&self, subscriber: Sender<PathChildrenCacheEvent>) -> Subscription {
        self.event_listeners.subscribe(subscriber)
    }

    pub fn remove_listener(&self, sub: Subscription) -> () {
        self.event_listeners.unsubscribe(sub)
    }

    fn offer_operation(&self, op: Operation) -> ZkResult<()> {
        match self.channel {
            Some(ref chan) => {
                chan.send(op).map_err(|err| {
                    warn!("error submitting op to channel: {:?}", err);
                    ZkError::APIError
                })
            },
            None => Err(ZkError::APIError)
        }
    }

}

pub fn join_path(dir: &str, child: &str) -> String {
    let dir_bytes = dir.as_bytes();
    let mut result = dir.to_string();
    if dir_bytes[dir_bytes.len() - 1] != ('/' as u8) {
        result.push_str("/");
    }
    result.push_str(child);
    result
}
<commit_msg>force get data after reconnect<commit_after>use std::thread;
use std::sync::{Arc, Mutex};
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};
use std::collections::HashMap;
use consts::{WatchedEventType, ZkError, ZkState};
use proto::WatchedEvent;
use zookeeper::{ZkResult, ZooKeeper};
use zookeeper_ext::ZooKeeperExt;
use listeners::{ListenerSet, Subscription};

pub type ChildData = Arc<Vec<u8>>;
pub type Data = HashMap<String, ChildData>;

#[derive(Debug,Clone)]
pub enum PathChildrenCacheEvent {
    Initialized,
    ConnectionSuspended,
    ConnectionLost,
    ConnectionReconnected,
    ChildRemoved(String),
    ChildAdded(String, ChildData),
    ChildUpdated(String, ChildData),
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum RefreshMode {
    Standard,
    ForceGetDataAndStat,
}

#[derive(Debug)]
pub enum Operation {
    Shutdown,
    Refresh(RefreshMode),
    Event(PathChildrenCacheEvent),
    GetData(String /* path */),
}

pub struct PathChildrenCache {
    path: Arc<String>,
    zk: Arc<ZooKeeper>,
    data: Arc<Mutex<Data>>,
    worker_thread: Option<thread::JoinHandle<()>>,
    channel: Option<Sender<Operation>>,
    listener_subscription: Option<Subscription>,
    event_listeners: ListenerSet<PathChildrenCacheEvent>,
}

impl PathChildrenCache {

    fn get_children(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>, ops_chan: Sender<Operation>, mode: RefreshMode) -> ZkResult<()> {
        let ops_chan1 = ops_chan.clone();

        let watcher = move |event: &WatchedEvent| {
            match event.event_type {
                WatchedEventType::NodeChildrenChanged => {
                    let _path = event.path.as_ref().expect("Path absent");

                    // Subscribe to new changes recursively
                    match ops_chan1.send(Operation::Refresh(RefreshMode::Standard)) {
                        Err(err) => {
                            warn!("error sending Refresh operation to ops channel: {:?}", err);
                        },
                        _ => {}
                    };
                },
                _ => error!("Unexpected: {:?}", event)
            };
        };

        let children = try!(zk.get_children_w(&path, watcher));

        let mut data_locked = data.lock().unwrap();

        for child in children.iter() {
            let child_path = join_path(path, child);

            if mode == RefreshMode::ForceGetDataAndStat || !data_locked.contains_key(&child_path) {

                let child_data = try!(Self::get_data(zk.clone(), &child_path, data.clone(), ops_chan.clone()));

                let child_data = Arc::new(child_data);

                data_locked.insert(child_path.clone(), child_data.clone());

                try!(ops_chan.send(Operation::Event(PathChildrenCacheEvent::ChildAdded(child_path, child_data))).map_err(|err| {
                    info!("error sending ChildAdded event: {:?}", err);
                    ZkError::APIError
                }));
            }
        }

        debug!("New data: {:?}", *data_locked);

        Ok(())
    }

    fn get_data(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>, ops_chan: Sender<Operation>) -> ZkResult<Vec<u8>> {
        let path1 = path.to_owned();

        let data_watcher = move |event: &WatchedEvent| {
            let mut data_locked = data.lock().unwrap();
            match event.event_type {
                WatchedEventType::NodeDeleted => {
                    data_locked.remove(&path1);

                    match ops_chan.send(Operation::Event(PathChildrenCacheEvent::ChildRemoved(path1.clone()))) {
                        Err(err) => {
                            warn!("error sending ChildRemoved event: {:?}", err);
                        },
                        _ => {}
                    }
                },
                WatchedEventType::NodeDataChanged => {
                    // Subscribe to new changes recursively
                    match ops_chan.send(Operation::GetData(path1)) {
                        Err(err) => {
                            warn!("error sending GetData to op channel: {:?}", err);
                        },
                        _ => {}
                    }
                },
                _ => error!("Unexpected: {:?}", event)
            };

            debug!("New data: {:?}", *data_locked);
        };

        zk.get_data_w(path, data_watcher).map(|stuff| { stuff.0 })
    }

    fn update_data(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>, ops_chan_tx: Sender<Operation>) -> ZkResult<()> {
        let mut data_locked = data.lock().unwrap();

        let path = path.to_owned();

        let result = Self::get_data(zk.clone(), &path, data.clone(), ops_chan_tx.clone());

        match result {
            Ok(child_data) => {
                info!("got data {:?}", child_data);

                let child_data = Arc::new(child_data);

                data_locked.insert(path.clone(), child_data.clone());

                ops_chan_tx.send(Operation::Event(PathChildrenCacheEvent::ChildUpdated(path, child_data))).map_err(|err| {
                    warn!("error sending ChildUpdated event: {:?}", err);
                    ZkError::APIError
                })
            },
            Err(err) => {
                warn!("error getting child data: {:?}", err);
                Err(ZkError::APIError)
            }
        }
    }

    pub fn new(zk: Arc<ZooKeeper>, path: &str) -> ZkResult<PathChildrenCache> {

        let data = Arc::new(Mutex::new(HashMap::new()));

        try!(zk.ensure_path(path));

        Ok(PathChildrenCache{
            path: Arc::new(path.to_string()),
            zk: zk,
            data: data,
            worker_thread: None,
            channel: None,
            listener_subscription: None,
            event_listeners: ListenerSet::new(),
        })
    }

    pub fn get_current_data(&self) -> Data {
        self.data.lock().unwrap().clone()
    }

    pub fn clear(&self) {
        self.data.lock().unwrap().clear()
    }

    fn handle_state_change(state: ZkState, ops_chan_tx: Sender<Operation>) -> bool {
        let mut done = false;

        info!("zk state change {:?}", state);
        match state {
            ZkState::Connected => {
                match ops_chan_tx.send(Operation::Refresh(RefreshMode::ForceGetDataAndStat)) {
                    Err(err) => {
                        warn!("error sending Refresh to op channel: {:?}", err);
                        done = true;
                    },
                    _ => {}
                }
            },
            _ => {
            }
        }

        done
    }

    fn handle_operation(op: Operation, zk: Arc<ZooKeeper>, path: Arc<String>, data: Arc<Mutex<Data>>, event_listeners: ListenerSet<PathChildrenCacheEvent>, ops_chan_tx: Sender<Operation>) -> bool {
        let mut done = false;

        debug!("handling op {:?}", op);
        match op {
            Operation::Shutdown => {
                info!("shutting down worker thread");
                done = true;
            },
            Operation::Refresh(mode) => {
                debug!("getting children");
                let result = Self::get_children(zk.clone(), &*path, data.clone(), ops_chan_tx.clone(), mode);
                info!("got children {:?}", result);
            },
            Operation::GetData(path) => {
                debug!("getting data");
                let result = Self::update_data(zk.clone(), &*path, data.clone(), ops_chan_tx.clone());
                match result {
                    Err(err) => {
                        warn!("error getting child data: {:?}", err);
                    },
                    _ => {}
                }
            },
            Operation::Event(event) => {
                info!("received event {:?}", event);
                event_listeners.notify(&event);
            },
        }

        done
    }

    pub fn start(&mut self) -> ZkResult<()> {
        let (ops_chan_tx, ops_chan_rx) = mpsc::channel();
        let (listener_chan_tx, listener_chan_rx) = mpsc::channel();

        let sub = self.zk.add_listener(listener_chan_tx.clone());
        self.listener_subscription = Some(sub);

        let zk = self.zk.clone();
        let path = self.path.clone();
        let data = self.data.clone();
        let event_listeners = self.event_listeners.clone();
        self.channel = Some(ops_chan_tx.clone());

        self.worker_thread = Some(thread::spawn(move || {
            let mut done = false;

            while !done {
                select! (
                    state_result = listener_chan_rx.recv() => {
                        match state_result {
                            Ok(state) => {
                                done = Self::handle_state_change(state, ops_chan_tx.clone());
                            },
                            Err(err) => {
                                info!("zk state chan err. shutting down. {:?}", err);
                                done = true;
                            }
                        }
                    },
                    op_result = ops_chan_rx.recv() => {
                        match op_result {
                            Ok(operation) => {
                                done = Self::handle_operation(operation, zk.clone(), path.clone(), data.clone(), event_listeners.clone(), ops_chan_tx.clone());
                            },
                            Err(err) => {
                                info!("error receiving from operations channel ({:?}). shutting down worker thread", err);
                                done = true;
                            }
                        }
                    });
            }
        }));

        self.offer_operation(Operation::Refresh(RefreshMode::ForceGetDataAndStat))
    }

    pub fn add_listener(&self, subscriber: Sender<PathChildrenCacheEvent>) -> Subscription {
        self.event_listeners.subscribe(subscriber)
    }

    pub fn remove_listener(&self, sub: Subscription) -> () {
        self.event_listeners.unsubscribe(sub)
    }

    fn offer_operation(&self, op: Operation) -> ZkResult<()> {
        match self.channel {
            Some(ref chan) => {
                chan.send(op).map_err(|err| {
                    warn!("error submitting op to channel: {:?}", err);
                    ZkError::APIError
                })
            },
            None => Err(ZkError::APIError)
        }
    }

}

pub fn join_path(dir: &str, child: &str) -> String {
    let dir_bytes = dir.as_bytes();
    let mut result = dir.to_string();
    if dir_bytes[dir_bytes.len() - 1] != ('/' as u8) {
        result.push_str("/");
    }
    result.push_str(child);
    result
}
<|endoftext|>


<commit_before>/// low level wrapper for the state machine, encoding and decoding from lapin-async
use lapin_async::connection::*;
use lapin_async::format::frame::*;

use nom::{IResult,Offset};
use cookie_factory::GenError;
use bytes::BytesMut;
use std::cmp;
use std::iter::repeat;
use std::io::{self,Error,ErrorKind};
use futures::{Async,Poll,Sink,Stream,StartSend,Future,future};
use tokio_io::{AsyncRead,AsyncWrite};
use tokio_io::codec::{Decoder,Encoder,Framed};
use channel::BasicProperties;
use client::ConnectionOptions;

/// implements tokio-io's Decoder and Encoder
pub struct AMQPCodec {
    pub frame_max: u32,
}

impl Decoder for AMQPCodec {
    type Item = Frame;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Frame>, io::Error> {
        let (consumed, f) = match frame(buf) {
          IResult::Incomplete(_) => {
            return Ok(None)
          },
          IResult::Error(e) => {
            return Err(io::Error::new(io::ErrorKind::Other, format!("parse error: {:?}", e)))
          },
          IResult::Done(i, frame) => {
            (buf.offset(i), frame)
          }
        };

        trace!("decoded frame: {:?}", f);

        buf.split_to(consumed);

        Ok(Some(f))
    }
}

impl Encoder for AMQPCodec {
    type Item = Frame;
    type Error = io::Error;

    fn encode(&mut self, frame: Frame, buf: &mut BytesMut) -> Result<(), Self::Error> {
      let length    = buf.len();
      // Ensure we at least allocate 8192 so that the buffer is big enough for the frame_max
      // negociation. Afterwards, use frame_max if > 8192.
      let frame_max = cmp::max(self.frame_max, 8192) as usize;
      if length < frame_max {
        //reserve more capacity and intialize it
        buf.extend(repeat(0).take(frame_max - length));
      }
      trace!("will encode and write frame: {:?}", frame);

      loop {
        let gen_res = match &frame {
          &Frame::ProtocolHeader => {
            gen_protocol_header((buf, 0)).map(|tup| tup.1)
          },
          &Frame::Heartbeat(_) => {
            gen_heartbeat_frame((buf, 0)).map(|tup| tup.1)
          },
          &Frame::Method(channel, ref method) => {
            gen_method_frame((buf, 0), channel, method).map(|tup| tup.1)
          },
          &Frame::Header(channel_id, class_id, ref header) => {
            gen_content_header_frame((buf, 0), channel_id, class_id, header.body_size, &header.properties).map(|tup| tup.1)
          },
          &Frame::Body(channel_id, ref data) => {
            gen_content_body_frame((buf, 0), channel_id, data).map(|tup| tup.1)
          }
        };

        match gen_res {
          Ok(sz) => {
            buf.truncate(sz);
            trace!("serialized frame: {} bytes", sz);
            return Ok(());
          },
          Err(e) => {
            error!("error generating frame: {:?}", e);
            match e {
              GenError::BufferTooSmall(sz) => {
                buf.extend(repeat(0).take(sz - length));
                //return Err(Error::new(ErrorKind::InvalidData, "send buffer too small"));
              },
              GenError::InvalidOffset | GenError::CustomError(_) | GenError::NotYetImplemented => {
                return Err(Error::new(ErrorKind::InvalidData, "could not generate"));
              }
            }
          }
        }
      }
    }
}

/// Wrappers over a `Framed` stream using `AMQPCodec` and lapin-async's `Connection`
pub struct AMQPTransport<T> {
  upstream: Framed<T,AMQPCodec>,
  pub conn: Connection,
}

impl<T> AMQPTransport<T>
   where T: AsyncRead+AsyncWrite,
         T: Sync+Send,
         T: 'static               {

  /// starts the connection process
  ///
  /// returns a future of a `AMQPTransport` that is connected
  pub fn connect(stream: T, options: &ConnectionOptions) -> Box<Future<Item = AMQPTransport<T>, Error = io::Error>> {
    let mut conn = Connection::new();
    conn.set_credentials(&options.username, &options.password);
    conn.set_vhost(&options.vhost);
    conn.set_frame_max(options.frame_max);
    conn.set_heartbeat(options.heartbeat);
    if let Err(e) = conn.connect() {
      let err = format!("Failed to connect: {:?}", e);
      return Box::new(future::err(Error::new(ErrorKind::ConnectionAborted, err)));
    }

    let codec = AMQPCodec {
      frame_max: conn.configuration.frame_max,
    };
    let mut t = AMQPTransport {
      upstream:  stream.framed(codec),
      conn:      conn,
    };

    if let Err(e) = t.send_and_handle_frames() {
      let err = format!("Failed to handle frames: {:?}", e);
      return Box::new(future::err(Error::new(ErrorKind::ConnectionAborted, err)));
    }

    let mut connector = AMQPTransportConnector {
      transport: Some(t),
    };

    trace!("pre-poll");
    if let Err(e) = connector.poll() {
      let err = format!("Failed to handle frames: {:?}", e);
      return Box::new(future::err(Error::new(ErrorKind::ConnectionAborted, err)));
    }
    trace!("post-poll");

    Box::new(connector)
  }

  pub fn send_and_handle_frames(&mut self) -> Poll<Option<()>, io::Error> {
    self.send_frames()?;
    self.handle_frames()
  }

  pub fn send_and_handle_frames_with_payload(&mut self, channel_id: u16, payload: &[u8], properties: BasicProperties) -> Poll<Option<()>, io::Error> {
      self.send_and_handle_frames()?;
      self.conn.send_content_frames(channel_id, 60, payload, properties);
      self.send_and_handle_frames()
  }

  fn send_frames(&mut self) -> Result<(), io::Error> {
    //FIXME: find a way to use a future here
    trace!("send frames");
    while let Some(f) = self.conn.next_frame() {
      if let Err(e) = self.send_frame(f) {
        error!("Failed to send frame: {:?}", e);
        return Err(e);
      }
    }
    Ok(())
  }

  pub fn send_frame(&mut self, frame: Frame) -> Poll<(), io::Error> {
      self.start_send(frame).and_then(|_| self.poll_complete())
  }

  fn handle_frames(&mut self) -> Poll<Option<()>, io::Error> {
    trace!("handle frames");
    for _ in 0..30 {
      if try_ready!(self.poll()).is_none() {
        return Ok(Async::Ready(None));
      }
    }
    self.poll()
  }
}

/// implements a future of `AMQPTransport`
///
/// this structure is used to perform the AMQP handshake and provide
/// a connected transport afterwards
pub struct AMQPTransportConnector<T> {
  pub transport: Option<AMQPTransport<T>>,
}

impl<T> Future for AMQPTransportConnector<T>
    where T: AsyncRead + AsyncWrite,
          T: Sync+Send,
          T: 'static {

  type Item  = AMQPTransport<T>;
  type Error = io::Error;

  fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
    debug!("AMQPTransportConnector poll transport is none? {}", self.transport.is_none());
    let mut transport = self.transport.take().unwrap();

    //we might have received a frame before here
    transport.send_and_handle_frames()?;

    debug!("conn state: {:?}", transport.conn.state);
    if transport.conn.state == ConnectionState::Connected {
      debug!("already connected");
      return Ok(Async::Ready(transport))
    }

    trace!("waiting before poll");
    match transport.poll()? {
      Async::Ready(Some(_)) => {
        if transport.conn.state == ConnectionState::Connected {
          // Upstream had frames available and we're connected, the transport is ready
          Ok(Async::Ready(transport))
        } else {
          // Upstream had frames but we're not yet connected, continue polling
          let poll_ret = transport.poll();
          self.transport = Some(transport);
          poll_ret?;
          Ok(Async::NotReady)
        }
      },
      _ => {
        // Upstream had no frames
        self.transport = Some(transport);
        Ok(Async::NotReady)
      },
    }
  }
}

impl<T> Stream for AMQPTransport<T>
    where T: AsyncRead + AsyncWrite,
          T: Sync+Send,
          T: 'static {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<()>, io::Error> {
        trace!("stream poll");
        let value = match self.upstream.poll() {
            Ok(Async::Ready(t)) => t,
            Ok(Async::NotReady) => {
                trace!("upstream poll gave NotReady");
                return Ok(Async::NotReady);
            },
            Err(e) => {
                error!("upstream poll gave error: {:?}", e);
                return Err(From::from(e));
            },
        };

        if let Some(frame) = value {
            trace!("upstream poll gave frame: {:?}", frame);
            if let Err(e) = self.conn.handle_frame(frame) {
                let err = format!("failed to handle frame: {:?}", e);
                return Err(io::Error::new(io::ErrorKind::Other, err));
            }
            self.send_frames()?;
            Ok(Async::Ready(Some(())))
        } else {
            error!("upstream poll gave Ready(None)");
            Ok(Async::Ready(None))
        }
    }
}

impl<T> Sink for AMQPTransport<T>
    where T: AsyncWrite,
          T: Sync+Send {
    type SinkItem = Frame;
    type SinkError = io::Error;

    fn start_send(&mut self, item: Frame) -> StartSend<Frame, io::Error> {
        trace!("sink start send");
        self.upstream.start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), io::Error> {
        trace!("sink poll_complete");
        self.upstream.poll_complete()
    }
}
<commit_msg>futures: loop while we get incoming data<commit_after>/// low level wrapper for the state machine, encoding and decoding from lapin-async
use lapin_async::connection::*;
use lapin_async::format::frame::*;

use nom::{IResult,Offset};
use cookie_factory::GenError;
use bytes::BytesMut;
use std::cmp;
use std::iter::repeat;
use std::io::{self,Error,ErrorKind};
use futures::{Async,Poll,Sink,Stream,StartSend,Future,future};
use tokio_io::{AsyncRead,AsyncWrite};
use tokio_io::codec::{Decoder,Encoder,Framed};
use channel::BasicProperties;
use client::ConnectionOptions;

/// implements tokio-io's Decoder and Encoder
pub struct AMQPCodec {
    pub frame_max: u32,
}

impl Decoder for AMQPCodec {
    type Item = Frame;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Frame>, io::Error> {
        let (consumed, f) = match frame(buf) {
          IResult::Incomplete(_) => {
            return Ok(None)
          },
          IResult::Error(e) => {
            return Err(io::Error::new(io::ErrorKind::Other, format!("parse error: {:?}", e)))
          },
          IResult::Done(i, frame) => {
            (buf.offset(i), frame)
          }
        };

        trace!("decoded frame: {:?}", f);

        buf.split_to(consumed);

        Ok(Some(f))
    }
}

impl Encoder for AMQPCodec {
    type Item = Frame;
    type Error = io::Error;

    fn encode(&mut self, frame: Frame, buf: &mut BytesMut) -> Result<(), Self::Error> {
      let length    = buf.len();
      // Ensure we at least allocate 8192 so that the buffer is big enough for the frame_max
      // negociation. Afterwards, use frame_max if > 8192.
      let frame_max = cmp::max(self.frame_max, 8192) as usize;
      if length < frame_max {
        //reserve more capacity and intialize it
        buf.extend(repeat(0).take(frame_max - length));
      }
      trace!("will encode and write frame: {:?}", frame);

      loop {
        let gen_res = match &frame {
          &Frame::ProtocolHeader => {
            gen_protocol_header((buf, 0)).map(|tup| tup.1)
          },
          &Frame::Heartbeat(_) => {
            gen_heartbeat_frame((buf, 0)).map(|tup| tup.1)
          },
          &Frame::Method(channel, ref method) => {
            gen_method_frame((buf, 0), channel, method).map(|tup| tup.1)
          },
          &Frame::Header(channel_id, class_id, ref header) => {
            gen_content_header_frame((buf, 0), channel_id, class_id, header.body_size, &header.properties).map(|tup| tup.1)
          },
          &Frame::Body(channel_id, ref data) => {
            gen_content_body_frame((buf, 0), channel_id, data).map(|tup| tup.1)
          }
        };

        match gen_res {
          Ok(sz) => {
            buf.truncate(sz);
            trace!("serialized frame: {} bytes", sz);
            return Ok(());
          },
          Err(e) => {
            error!("error generating frame: {:?}", e);
            match e {
              GenError::BufferTooSmall(sz) => {
                buf.extend(repeat(0).take(sz - length));
                //return Err(Error::new(ErrorKind::InvalidData, "send buffer too small"));
              },
              GenError::InvalidOffset | GenError::CustomError(_) | GenError::NotYetImplemented => {
                return Err(Error::new(ErrorKind::InvalidData, "could not generate"));
              }
            }
          }
        }
      }
    }
}

/// Wrappers over a `Framed` stream using `AMQPCodec` and lapin-async's `Connection`
pub struct AMQPTransport<T> {
  upstream: Framed<T,AMQPCodec>,
  pub conn: Connection,
}

impl<T> AMQPTransport<T>
   where T: AsyncRead+AsyncWrite,
         T: Sync+Send,
         T: 'static               {

  /// starts the connection process
  ///
  /// returns a future of a `AMQPTransport` that is connected
  pub fn connect(stream: T, options: &ConnectionOptions) -> Box<Future<Item = AMQPTransport<T>, Error = io::Error>> {
    let mut conn = Connection::new();
    conn.set_credentials(&options.username, &options.password);
    conn.set_vhost(&options.vhost);
    conn.set_frame_max(options.frame_max);
    conn.set_heartbeat(options.heartbeat);
    if let Err(e) = conn.connect() {
      let err = format!("Failed to connect: {:?}", e);
      return Box::new(future::err(Error::new(ErrorKind::ConnectionAborted, err)));
    }

    let codec = AMQPCodec {
      frame_max: conn.configuration.frame_max,
    };
    let mut t = AMQPTransport {
      upstream:  stream.framed(codec),
      conn:      conn,
    };

    if let Err(e) = t.send_and_handle_frames() {
      let err = format!("Failed to handle frames: {:?}", e);
      return Box::new(future::err(Error::new(ErrorKind::ConnectionAborted, err)));
    }

    let mut connector = AMQPTransportConnector {
      transport: Some(t),
    };

    trace!("pre-poll");
    if let Err(e) = connector.poll() {
      let err = format!("Failed to handle frames: {:?}", e);
      return Box::new(future::err(Error::new(ErrorKind::ConnectionAborted, err)));
    }
    trace!("post-poll");

    Box::new(connector)
  }

  pub fn send_and_handle_frames(&mut self) -> Poll<Option<()>, io::Error> {
    self.send_frames()?;
    self.handle_frames()
  }

  pub fn send_and_handle_frames_with_payload(&mut self, channel_id: u16, payload: &[u8], properties: BasicProperties) -> Poll<Option<()>, io::Error> {
      self.send_and_handle_frames()?;
      self.conn.send_content_frames(channel_id, 60, payload, properties);
      self.send_and_handle_frames()
  }

  fn send_frames(&mut self) -> Result<(), io::Error> {
    //FIXME: find a way to use a future here
    trace!("send frames");
    while let Some(f) = self.conn.next_frame() {
      if let Err(e) = self.send_frame(f) {
        error!("Failed to send frame: {:?}", e);
        return Err(e);
      }
    }
    Ok(())
  }

  pub fn send_frame(&mut self, frame: Frame) -> Poll<(), io::Error> {
      self.start_send(frame).and_then(|_| self.poll_complete())
  }

  fn handle_frames(&mut self) -> Poll<Option<()>, io::Error> {
    trace!("handle frames");
    loop {
      // try_ready will return if we hit an error or NotReady.
      if try_ready!(self.poll()).is_none() {
        return Ok(Async::Ready(None));
      }
    }
  }
}

/// implements a future of `AMQPTransport`
///
/// this structure is used to perform the AMQP handshake and provide
/// a connected transport afterwards
pub struct AMQPTransportConnector<T> {
  pub transport: Option<AMQPTransport<T>>,
}

impl<T> Future for AMQPTransportConnector<T>
    where T: AsyncRead + AsyncWrite,
          T: Sync+Send,
          T: 'static {

  type Item  = AMQPTransport<T>;
  type Error = io::Error;

  fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
    debug!("AMQPTransportConnector poll transport is none? {}", self.transport.is_none());
    let mut transport = self.transport.take().unwrap();

    //we might have received a frame before here
    transport.send_and_handle_frames()?;

    debug!("conn state: {:?}", transport.conn.state);
    if transport.conn.state == ConnectionState::Connected {
      debug!("already connected");
      return Ok(Async::Ready(transport))
    }

    trace!("waiting before poll");
    match transport.poll()? {
      Async::Ready(Some(_)) => {
        if transport.conn.state == ConnectionState::Connected {
          // Upstream had frames available and we're connected, the transport is ready
          Ok(Async::Ready(transport))
        } else {
          // Upstream had frames but we're not yet connected, continue polling
          let poll_ret = transport.poll();
          self.transport = Some(transport);
          poll_ret?;
          Ok(Async::NotReady)
        }
      },
      _ => {
        // Upstream had no frames
        self.transport = Some(transport);
        Ok(Async::NotReady)
      },
    }
  }
}

impl<T> Stream for AMQPTransport<T>
    where T: AsyncRead + AsyncWrite,
          T: Sync+Send,
          T: 'static {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<()>, io::Error> {
        trace!("stream poll");
        let value = match self.upstream.poll() {
            Ok(Async::Ready(t)) => t,
            Ok(Async::NotReady) => {
                trace!("upstream poll gave NotReady");
                return Ok(Async::NotReady);
            },
            Err(e) => {
                error!("upstream poll gave error: {:?}", e);
                return Err(From::from(e));
            },
        };

        if let Some(frame) = value {
            trace!("upstream poll gave frame: {:?}", frame);
            if let Err(e) = self.conn.handle_frame(frame) {
                let err = format!("failed to handle frame: {:?}", e);
                return Err(io::Error::new(io::ErrorKind::Other, err));
            }
            self.send_frames()?;
            Ok(Async::Ready(Some(())))
        } else {
            error!("upstream poll gave Ready(None)");
            Ok(Async::Ready(None))
        }
    }
}

impl<T> Sink for AMQPTransport<T>
    where T: AsyncWrite,
          T: Sync+Send {
    type SinkItem = Frame;
    type SinkError = io::Error;

    fn start_send(&mut self, item: Frame) -> StartSend<Frame, io::Error> {
        trace!("sink start send");
        self.upstream.start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), io::Error> {
        trace!("sink poll_complete");
        self.upstream.poll_complete()
    }
}
<|endoftext|>


<commit_before><commit_msg>Test code fixes: fmt::Show changed from {} to {:?}<commit_after><|endoftext|>


<commit_before>extern crate clap;
extern crate rusqlite;
#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;
extern crate rustc_serialize;
extern crate serde_yaml;
extern crate uuid;
#[cfg(test)]
#[macro_use]
extern crate proptest;

mod actions_process;
mod actions_process_list_provides;
mod autoconf;
mod clap_actions;
mod clap_fern;
mod cli_clap;
mod db;
mod db_enviroment;
mod db_fs_dir;
use db::fs_dir_type;
mod db_fs_file;
use db::db_job;
mod db_job_depend;
mod db_job_provide;
mod db_job_require_variable;
mod db_job_require_variable_pair;
use db::db_provider;
use db::db_session;
mod db_variable_name;
mod db_variable_pair;
mod elephant;
mod jobs_load;
mod json_loader_elephant;
mod loader;
use uuid::Uuid;

fn main() {
    let some_value = 10;
    let clap_matches = cli_clap::cli_clap(&some_value);
    let actions = clap_actions::actions_get(&clap_matches);
    clap_fern::log_setup(&clap_matches);
    let session_uuid = Uuid::new_v4();
    let session_uuid_string = session_uuid.hyphenated().to_string();
    trace!("session_uuid_string:{}", session_uuid_string);
    let conn = loader::connect_deligate(&clap_matches);
    db::create_tables(&conn);
    loader::deligate(&conn, &actions, &clap_matches);
    let pk_session = elephant::elephant_session(&conn, &session_uuid_string);
    loader::enviroment(&conn, pk_session, &clap_matches);
    jobs_load::load(&conn);
    actions_process::process(&conn, &actions)
}
<commit_msg>Add central configuration structure<commit_after>extern crate clap;
extern crate rusqlite;
#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;
extern crate rustc_serialize;
extern crate serde_yaml;
extern crate uuid;
#[cfg(test)]
#[macro_use]
extern crate proptest;

mod actions_process;
mod actions_process_list_provides;
mod autoconf;
mod cfg;
mod clap_actions;
mod clap_fern;
mod cli_clap;
mod db;
mod db_enviroment;
mod db_fs_dir;
use db::fs_dir_type;
mod db_fs_file;
use db::db_job;
mod db_job_depend;
mod db_job_provide;
mod db_job_require_variable;
mod db_job_require_variable_pair;
use db::db_provider;
use db::db_session;
mod db_variable_name;
mod db_variable_pair;
mod elephant;
mod jobs_load;
mod json_loader_elephant;
mod loader;
use uuid::Uuid;

fn main() {
    let mut runtime_cfg = cfg::Config::new().unwrap();
    let pointless_value = 10; // pointless variable due to not knowing about lifetimes
    let clap_matches = cli_clap::cli_clap(&pointless_value);
    clap_fern::log_setup(&clap_matches);
    clap_actions::cfg_actions_update_clap(&mut runtime_cfg, &clap_matches);
    let session_uuid = Uuid::new_v4();
    let session_uuid_string = session_uuid.hyphenated().to_string();
    trace!("session_uuid_string:{}", session_uuid_string);
    let conn = actions_process::cfg_process_action_db_connect(&mut runtime_cfg);
    db::create_tables(&conn);
    loader::deligate(&conn, &mut runtime_cfg);
    let pk_session = elephant::elephant_session(&conn, &session_uuid_string);
    loader::enviroment(&conn, &mut runtime_cfg, pk_session);
    jobs_load::load(&conn);
    actions_process::process(&conn, &runtime_cfg)
}
<|endoftext|>


<commit_before>/// ! A Dominator Tree represented as mappings of Ebbs to their immediate dominator.

use cfg::*;
use ir::entities::Ebb;
use entity_map::EntityMap;

pub struct DominatorTree {
    data: EntityMap<Ebb, Option<Ebb>>,
}

impl DominatorTree {
    pub fn new(cfg: &ControlFlowGraph) -> DominatorTree {
        let mut dt = DominatorTree { data: EntityMap::new() };
        dt.build(cfg);
        dt
    }

    pub fn build(&mut self, cfg: &ControlFlowGraph) {
        let reverse_postorder_map = cfg.reverse_postorder_ebbs();
        let ebbs = reverse_postorder_map.keys().collect::<Vec<Ebb>>();
        let len = reverse_postorder_map.len();

        for (i, ebb) in ebbs.iter().enumerate() {
            if i > 0 {
                self.data.push(None);
            } else {
                self.data.push(Some(ebb.clone()));
            }
        }

        let mut changed = len > 0;

        while changed {
            changed = false;
            for i in 1..len {
                let ebb = ebbs[i];
                let preds = cfg.get_predecessors(ebb);
                let mut new_idom = None;

                for &(p, _) in preds {
                    if new_idom == None {
                        new_idom = Some(p);
                        continue;
                    }
                    if let Some(_) = self.data[p] {
                        new_idom =
                            Some(self.intersect(&reverse_postorder_map, p, new_idom.unwrap()));
                    }
                }
                match self.data[ebb] {
                    None => {
                        self.data[ebb] = new_idom;
                        changed = true;
                    }
                    Some(idom) => {
                        // Old idom != New idom
                        if idom != new_idom.unwrap() {
                            self.data[ebb] = new_idom;
                            changed = true;
                        }
                    }
                }
            }
        }
    }

    fn intersect(&self, ordering: &EntityMap<Ebb, usize>, first: Ebb, second: Ebb) -> Ebb {
        let mut a = first;
        let mut b = second;
        while a != b {
            while ordering[a] < ordering[b] {
                a = self.data[a].unwrap();
            }
            while ordering[b] < ordering[a] {
                b = self.data[b].unwrap();
            }
        }
        a
    }

    pub fn idom(&self, ebb: Ebb) -> Option<Ebb> {
        self.data[ebb].clone()
    }

    pub fn len(&self) -> usize {
        self.data.len()
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use ir::Function;
    use cfg::ControlFlowGraph;
    use test_utils::make_inst;

    #[test]
    fn empty() {
        let func = Function::new();
        let cfg = ControlFlowGraph::new(&func);
        let dtree = DominatorTree::new(&cfg);
        assert_eq!(dtree.len(), 0);
    }

    #[test]
    fn non_zero_entry_block() {
        let mut func = Function::new();
        let ebb3 = func.dfg.make_ebb();
        let ebb1 = func.dfg.make_ebb();
        let ebb2 = func.dfg.make_ebb();
        let ebb0 = func.dfg.make_ebb();
        func.layout.append_ebb(ebb3);
        func.layout.append_ebb(ebb1);
        func.layout.append_ebb(ebb2);
        func.layout.append_ebb(ebb0);

        let jmp_ebb3_ebb1 = make_inst::jump(&mut func, ebb1);
        let br_ebb1_ebb0 = make_inst::branch(&mut func, ebb0);
        let jmp_ebb1_ebb2 = make_inst::jump(&mut func, ebb2);
        let jmp_ebb2_ebb0 = make_inst::jump(&mut func, ebb0);

        func.layout.append_inst(br_ebb1_ebb0, ebb1);
        func.layout.append_inst(jmp_ebb1_ebb2, ebb1);
        func.layout.append_inst(jmp_ebb2_ebb0, ebb2);
        func.layout.append_inst(jmp_ebb3_ebb1, ebb3);

        let cfg = ControlFlowGraph::new(&func);
        let dt = DominatorTree::new(&cfg);

        assert_eq!(func.layout.entry_block().unwrap(), ebb3);
        assert_eq!(dt.len(), cfg.len());
        assert_eq!(dt.idom(ebb3).unwrap(), ebb3);
        assert_eq!(dt.idom(ebb1).unwrap(), ebb3);
        assert_eq!(dt.idom(ebb2).unwrap(), ebb1);
        assert_eq!(dt.idom(ebb0).unwrap(), ebb1);
    }
}
<commit_msg>Improve the structure and comments of the module.<commit_after>/// ! A Dominator Tree represented as mappings of Ebbs to their immediate dominator.

use cfg::*;
use ir::entities::Ebb;
use entity_map::EntityMap;

pub struct DominatorTree {
    data: EntityMap<Ebb, Option<Ebb>>,
}

impl DominatorTree {
    pub fn new(cfg: &ControlFlowGraph) -> DominatorTree {
        let mut dt = DominatorTree { data: EntityMap::with_capacity(cfg.len()) };
        dt.build(cfg);
        dt
    }

    /// Build a dominator tree from a control flow graph using Keith D. Cooper's
    /// "Simple, Fast Dominator Algorithm."
    fn build(&mut self, cfg: &ControlFlowGraph) {
        let reverse_postorder_map = cfg.reverse_postorder_ebbs();
        let ebbs = reverse_postorder_map.keys().collect::<Vec<Ebb>>();
        let len = reverse_postorder_map.len();

        let mut changed = false;

        if len > 0 {
            self.data[ebbs[0]] = Some(ebbs[0]);
            changed = true;
        }

        while changed {
            changed = false;
            for i in 1..len {
                let ebb = ebbs[i];
                let preds = cfg.get_predecessors(ebb);
                let mut new_idom = None;

                for &(p, _) in preds {
                    if new_idom == None {
                        new_idom = Some(p);
                        continue;
                    }
                    // If this predecessor `p` has an idom available find its common
                    // ancestor with the current value of new_idom.
                    if let Some(_) = self.data[p] {
                        new_idom = match new_idom {
                            Some(cur_idom) => {
                                Some(self.intersect(&reverse_postorder_map, p, cur_idom))
                            }
                            None => panic!("A 'current idom' should have been set!"),
                        }
                    }
                }
                match self.data[ebb] {
                    None => {
                        self.data[ebb] = new_idom;
                        changed = true;
                    }
                    Some(idom) => {
                        // Old idom != New idom
                        if idom != new_idom.unwrap() {
                            self.data[ebb] = new_idom;
                            changed = true;
                        }
                    }
                }
            }
        }
    }

    /// Find the common dominator of two ebbs.
    fn intersect(&self, ordering: &EntityMap<Ebb, usize>, first: Ebb, second: Ebb) -> Ebb {
        let mut a = first;
        let mut b = second;

        // Here we use 'ordering', a mapping of ebbs to their postorder
        // visitation number, to ensure that we move upward through the tree.
        // Walking upward means that we may always expect self.data[a] and
        // self.data[b] to contain non-None entries.
        while a != b {
            while ordering[a] < ordering[b] {
                a = self.data[a].unwrap();
            }
            while ordering[b] < ordering[a] {
                b = self.data[b].unwrap();
            }
        }
        a
    }

    /// Returns the immediate dominator of some ebb or None if the
    /// node is unreachable.
    pub fn idom(&self, ebb: Ebb) -> Option<Ebb> {
        self.data[ebb].clone()
    }

    /// The total number of nodes in the tree.
    pub fn len(&self) -> usize {
        self.data.len()
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use ir::Function;
    use cfg::ControlFlowGraph;
    use test_utils::make_inst;

    #[test]
    fn empty() {
        let func = Function::new();
        let cfg = ControlFlowGraph::new(&func);
        let dtree = DominatorTree::new(&cfg);
        assert_eq!(dtree.len(), 0);
    }

    #[test]
    fn non_zero_entry_block() {
        let mut func = Function::new();
        let ebb3 = func.dfg.make_ebb();
        let ebb1 = func.dfg.make_ebb();
        let ebb2 = func.dfg.make_ebb();
        let ebb0 = func.dfg.make_ebb();
        func.layout.append_ebb(ebb3);
        func.layout.append_ebb(ebb1);
        func.layout.append_ebb(ebb2);
        func.layout.append_ebb(ebb0);

        let jmp_ebb3_ebb1 = make_inst::jump(&mut func, ebb1);
        let br_ebb1_ebb0 = make_inst::branch(&mut func, ebb0);
        let jmp_ebb1_ebb2 = make_inst::jump(&mut func, ebb2);
        let jmp_ebb2_ebb0 = make_inst::jump(&mut func, ebb0);

        func.layout.append_inst(br_ebb1_ebb0, ebb1);
        func.layout.append_inst(jmp_ebb1_ebb2, ebb1);
        func.layout.append_inst(jmp_ebb2_ebb0, ebb2);
        func.layout.append_inst(jmp_ebb3_ebb1, ebb3);

        let cfg = ControlFlowGraph::new(&func);
        let dt = DominatorTree::new(&cfg);

        assert_eq!(func.layout.entry_block().unwrap(), ebb3);
        assert_eq!(dt.len(), cfg.len());
        assert_eq!(dt.idom(ebb3).unwrap(), ebb3);
        assert_eq!(dt.idom(ebb1).unwrap(), ebb3);
        assert_eq!(dt.idom(ebb2).unwrap(), ebb1);
        assert_eq!(dt.idom(ebb0).unwrap(), ebb1);
    }
}
<|endoftext|>