<commit_before>//! Support for capturing a stack backtrace of an OS thread
//!
//! This module contains the support necessary to capture a stack backtrace of a
//! running OS thread from the OS thread itself. The `Backtrace` type supports
//! capturing a stack trace via the `Backtrace::capture` and
//! `Backtrace::force_capture` functions.
//!
//! A backtrace is typically quite handy to attach to errors (e.g. types
//! implementing `std::error::Error`) to get a causal chain of where an error
//! was generated.
//!
//! > **Note**: this module is unstable and is designed in [RFC 2504], and you
//! > can learn more about its status in the [tracking issue].
//!
//! [RFC 2504]: https://github.com/rust-lang/rfcs/blob/master/text/2504-fix-error.md
//! [tracking issue]: https://github.com/rust-lang/rust/issues/53487
//!
//! ## Accuracy
//!
//! Backtraces are attempted to be as accurate as possible, but no guarantees
//! are provided about the exact accuracy of a backtrace. Instruction pointers,
//! symbol names, filenames, line numbers, etc, may all be incorrect when
//! reported. Accuracy is attempted on a best-effort basis, however, and bugs
//! are always welcome to indicate areas of improvement!
//!
//! For most platforms a backtrace with a filename/line number requires that
//! programs be compiled with debug information. Without debug information
//! filenames/line numbers will not be reported.
//!
//! ## Platform support
//!
//! Not all platforms that libstd compiles for support capturing backtraces.
//! Some platforms simply do nothing when capturing a backtrace. To check
//! whether the platform supports capturing backtraces you can consult the
//! `BacktraceStatus` enum as a result of `Backtrace::status`.
//!
//! Like above with accuracy platform support is done on a best effort basis.
//! Sometimes libraries may not be available at runtime or something may go
//! wrong which would cause a backtrace to not be captured. Please feel free to
//! report issues with platforms where a backtrace cannot be captured though!
//!
//! ## Environment Variables
//!
//! The `Backtrace::capture` function may not actually capture a backtrace by
//! default. Its behavior is governed by two environment variables:
//!
//! * `RUST_LIB_BACKTRACE` - if this is set to `0` then `Backtrace::capture`
//!   will never capture a backtrace. Any other value this is set to will enable
//!   `Backtrace::capture`.
//!
//! * `RUST_BACKTRACE` - if `RUST_LIB_BACKTRACE` is not set, then this variable
//!   is consulted with the same rules of `RUST_LIB_BACKTRACE`.
//!
//! * If neither of the above env vars are set, then `Backtrace::capture` will
//!   be disabled.
//!
//! Capturing a backtrace can be a quite expensive runtime operation, so the
//! environment variables allow either forcibly disabling this runtime
//! performance hit or allow selectively enabling it in some programs.
//!
//! Note that the `Backtrace::force_capture` function can be used to ignore
//! these environment variables. Also note that the state of environment
//! variables is cached once the first backtrace is created, so altering
//! `RUST_LIB_BACKTRACE` or `RUST_BACKTRACE` at runtime may not actually change
//! how backtraces are captured.

#![unstable(feature = "backtrace", issue = "53487")]

// NB: A note on resolution of a backtrace:
//
// Backtraces primarily happen in two steps, one is where we actually capture
// the stack backtrace, giving us a list of instruction pointers corresponding
// to stack frames. Next we take these instruction pointers and, one-by-one,
// turn them into a human readable name (like `main`).
//
// The first phase can be somewhat expensive (walking the stack), especially
// on MSVC where debug information is consulted to return inline frames each as
// their own frame. The second phase, however, is almost always extremely
// expensive (on the order of milliseconds sometimes) when it's consulting debug
// information.
//
// We attempt to amortize this cost as much as possible by delaying resolution
// of an address to a human readable name for as long as possible. When
// `Backtrace::create` is called to capture a backtrace it doesn't actually
// perform any symbol resolution, but rather we lazily resolve symbols only just
// before they're needed for printing. This way we can make capturing a
// backtrace and throwing it away much cheaper, but actually printing a
// backtrace is still basically the same cost.
//
// This strategy comes at the cost of some synchronization required inside of a
// `Backtrace`, but that's a relatively small price to pay relative to capturing
// a backtrace or actually symbolizing it.

use crate::env;
use crate::fmt;
use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
use crate::sync::Mutex;
use crate::sys_common::backtrace::{lock, output_filename};
use crate::vec::Vec;
use backtrace::BytesOrWideString;
use backtrace_rs as backtrace;

/// A captured OS thread stack backtrace.
///
/// This type represents a stack backtrace for an OS thread captured at a
/// previous point in time. In some instances the `Backtrace` type may
/// internally be empty due to configuration. For more information see
/// `Backtrace::capture`.
pub struct Backtrace {
    inner: Inner,
}

/// The current status of a backtrace, indicating whether it was captured or
/// whether it is empty for some other reason.
#[non_exhaustive]
#[derive(Debug, PartialEq, Eq)]
pub enum BacktraceStatus {
    /// Capturing a backtrace is not supported, likely because it's not
    /// implemented for the current platform.
    Unsupported,
    /// Capturing a backtrace has been disabled through either the
    /// `RUST_LIB_BACKTRACE` or `RUST_BACKTRACE` environment variables.
    Disabled,
    /// A backtrace has been captured and the `Backtrace` should print
    /// reasonable information when rendered.
    Captured,
}

enum Inner {
    Unsupported,
    Disabled,
    Captured(Mutex<Capture>),
}

struct Capture {
    actual_start: usize,
    resolved: bool,
    frames: Vec<BacktraceFrame>,
}

fn _assert_send_sync() {
    fn _assert<T: Send + Sync>() {}
    _assert::<Backtrace>();
}

struct BacktraceFrame {
    frame: backtrace::Frame,
    symbols: Vec<BacktraceSymbol>,
}

struct BacktraceSymbol {
    name: Option<Vec<u8>>,
    filename: Option<BytesOrWide>,
    lineno: Option<u32>,
}

enum BytesOrWide {
    Bytes(Vec<u8>),
    Wide(Vec<u16>),
}

impl fmt::Debug for Backtrace {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut capture = match &self.inner {
            Inner::Unsupported => return fmt.write_str("unsupported backtrace"),
            Inner::Disabled => return fmt.write_str("disabled backtrace"),
            Inner::Captured(c) => c.lock().unwrap(),
        };
        capture.resolve();

        let mut dbg = fmt.debug_list();

        for frame in &capture.frames {
            dbg.entries(&frame.symbols);
        }

        dbg.finish()
    }
}

impl fmt::Debug for BacktraceSymbol {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut dbg = fmt.debug_struct("");
        dbg.field("fn", &self.name.as_ref().map(|b| backtrace::SymbolName::new(b)));

        if let Some(fname) = self.filename.as_ref() {
            dbg.field("file", fname);
        }

        if let Some(line) = self.lineno.as_ref() {
            dbg.field("line", line);
        }

        dbg.finish()
    }
}

impl fmt::Debug for BytesOrWide {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        output_filename(
            fmt,
            match self {
                BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w),
                BytesOrWide::Wide(w) => BytesOrWideString::Wide(w),
            },
            backtrace::PrintFmt::Full,
            crate::env::current_dir().as_ref().ok(),
        )
    }
}

impl Backtrace {
    /// Returns whether backtrace captures are enabled through environment
    /// variables.
    fn enabled() -> bool {
        // Cache the result of reading the environment variables to make
        // backtrace captures speedy, because otherwise reading environment
        // variables every time can be somewhat slow.
        static ENABLED: AtomicUsize = AtomicUsize::new(0);
        match ENABLED.load(SeqCst) {
            0 => {}
            1 => return false,
            _ => return true,
        }
        let enabled = match env::var("RUST_LIB_BACKTRACE") {
            Ok(s) => s != "0",
            Err(_) => match env::var("RUST_BACKTRACE") {
                Ok(s) => s != "0",
                Err(_) => false,
            },
        };
        ENABLED.store(enabled as usize + 1, SeqCst);
        return enabled;
    }

    /// Capture a stack backtrace of the current thread.
    ///
    /// This function will capture a stack backtrace of the current OS thread of
    /// execution, returning a `Backtrace` type which can be later used to print
    /// the entire stack trace or render it to a string.
    ///
    /// This function will be a noop if the `RUST_BACKTRACE` or
    /// `RUST_LIB_BACKTRACE` backtrace variables are both not set. If either
    /// environment variable is set and enabled then this function will actually
    /// capture a backtrace. Capturing a backtrace can be both memory intensive
    /// and slow, so these environment variables allow liberally using
    /// `Backtrace::capture` and only incurring a slowdown when the environment
    /// variables are set.
    ///
    /// To forcibly capture a backtrace regardless of environment variables, use
    /// the `Backtrace::force_capture` function.
    #[inline(never)] // want to make sure there's a frame here to remove
    pub fn capture() -> Backtrace {
        if !Backtrace::enabled() {
            return Backtrace { inner: Inner::Disabled };
        }
        Backtrace::create(Backtrace::capture as usize)
    }

    /// Forcibly captures a full backtrace, regardless of environment variable
    /// configuration.
    ///
    /// This function behaves the same as `capture` except that it ignores the
    /// values of the `RUST_BACKTRACE` and `RUST_LIB_BACKTRACE` environment
    /// variables, always capturing a backtrace.
    ///
    /// Note that capturing a backtrace can be an expensive operation on some
    /// platforms, so this should be used with caution in performance-sensitive
    /// parts of code.
    #[inline(never)] // want to make sure there's a frame here to remove
    pub fn force_capture() -> Backtrace {
        Backtrace::create(Backtrace::force_capture as usize)
    }

    // Capture a backtrace which start just before the function addressed by
    // `ip`
    fn create(ip: usize) -> Backtrace {
        let _lock = lock();
        let mut frames = Vec::new();
        let mut actual_start = None;
        unsafe {
            backtrace::trace_unsynchronized(|frame| {
                frames.push(BacktraceFrame { frame: frame.clone(), symbols: Vec::new() });
                if frame.symbol_address() as usize == ip && actual_start.is_none() {
                    actual_start = Some(frames.len());
                }
                true
            });
        }

        // If no frames came out assume that this is an unsupported platform
        // since `backtrace` doesn't provide a way of learning this right now,
        // and this should be a good enough approximation.
        let inner = if frames.len() == 0 {
            Inner::Unsupported
        } else {
            Inner::Captured(Mutex::new(Capture {
                actual_start: actual_start.unwrap_or(0),
                frames,
                resolved: false,
            }))
        };

        Backtrace { inner }
    }

    /// Returns the status of this backtrace, indicating whether this backtrace
    /// request was unsupported, disabled, or a stack trace was actually
    /// captured.
    pub fn status(&self) -> BacktraceStatus {
        match self.inner {
            Inner::Unsupported => BacktraceStatus::Unsupported,
            Inner::Disabled => BacktraceStatus::Disabled,
            Inner::Captured(_) => BacktraceStatus::Captured,
        }
    }
}

impl fmt::Display for Backtrace {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut capture = match &self.inner {
            Inner::Unsupported => return fmt.write_str("unsupported backtrace"),
            Inner::Disabled => return fmt.write_str("disabled backtrace"),
            Inner::Captured(c) => c.lock().unwrap(),
        };
        capture.resolve();

        let full = fmt.alternate();
        let (frames, style) = if full {
            (&capture.frames[..], backtrace::PrintFmt::Full)
        } else {
            (&capture.frames[capture.actual_start..], backtrace::PrintFmt::Short)
        };

        // When printing paths we try to strip the cwd if it exists, otherwise
        // we just print the path as-is. Note that we also only do this for the
        // short format, because if it's full we presumably want to print
        // everything.
        let cwd = crate::env::current_dir();
        let mut print_path = move |fmt: &mut fmt::Formatter<'_>, path: BytesOrWideString<'_>| {
            output_filename(fmt, path, style, cwd.as_ref().ok())
        };

        let mut f = backtrace::BacktraceFmt::new(fmt, style, &mut print_path);
        f.add_context()?;
        for frame in frames {
            let mut f = f.frame();
            if frame.symbols.is_empty() {
                f.print_raw(frame.frame.ip(), None, None, None)?;
            } else {
                for symbol in frame.symbols.iter() {
                    f.print_raw(
                        frame.frame.ip(),
                        symbol.name.as_ref().map(|b| backtrace::SymbolName::new(b)),
                        symbol.filename.as_ref().map(|b| match b {
                            BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w),
                            BytesOrWide::Wide(w) => BytesOrWideString::Wide(w),
                        }),
                        symbol.lineno,
                    )?;
                }
            }
        }
        f.finish()?;
        Ok(())
    }
}

impl Capture {
    fn resolve(&mut self) {
        // If we're already resolved, nothing to do!
        if self.resolved {
            return;
        }
        self.resolved = true;

        // Use the global backtrace lock to synchronize this as it's a
        // requirement of the `backtrace` crate, and then actually resolve
        // everything.
        let _lock = lock();
        for frame in self.frames.iter_mut() {
            let symbols = &mut frame.symbols;
            unsafe {
                backtrace::resolve_frame_unsynchronized(&frame.frame, |symbol| {
                    symbols.push(BacktraceSymbol {
                        name: symbol.name().map(|m| m.as_bytes().to_vec()),
                        filename: symbol.filename_raw().map(|b| match b {
                            BytesOrWideString::Bytes(b) => BytesOrWide::Bytes(b.to_owned()),
                            BytesOrWideString::Wide(b) => BytesOrWide::Wide(b.to_owned()),
                        }),
                        lineno: symbol.lineno(),
                    });
                });
            }
        }
    }
}

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

    #[test]
    fn debug_backtrace_fmt() {
        let bt = Backtrace::capture();
        eprintln!("uncaptured: {:?}", bt);
        let bt = Backtrace::force_capture();
        eprintln!("captured: {:?}", bt);
        eprintln!("display print: {}", bt);
        eprintln!("resolved: {:?}", bt);
        unimplemented!();
    }
}
<commit_msg>final format cleanups<commit_after>//! Support for capturing a stack backtrace of an OS thread
//!
//! This module contains the support necessary to capture a stack backtrace of a
//! running OS thread from the OS thread itself. The `Backtrace` type supports
//! capturing a stack trace via the `Backtrace::capture` and
//! `Backtrace::force_capture` functions.
//!
//! A backtrace is typically quite handy to attach to errors (e.g. types
//! implementing `std::error::Error`) to get a causal chain of where an error
//! was generated.
//!
//! > **Note**: this module is unstable and is designed in [RFC 2504], and you
//! > can learn more about its status in the [tracking issue].
//!
//! [RFC 2504]: https://github.com/rust-lang/rfcs/blob/master/text/2504-fix-error.md
//! [tracking issue]: https://github.com/rust-lang/rust/issues/53487
//!
//! ## Accuracy
//!
//! Backtraces are attempted to be as accurate as possible, but no guarantees
//! are provided about the exact accuracy of a backtrace. Instruction pointers,
//! symbol names, filenames, line numbers, etc, may all be incorrect when
//! reported. Accuracy is attempted on a best-effort basis, however, and bugs
//! are always welcome to indicate areas of improvement!
//!
//! For most platforms a backtrace with a filename/line number requires that
//! programs be compiled with debug information. Without debug information
//! filenames/line numbers will not be reported.
//!
//! ## Platform support
//!
//! Not all platforms that libstd compiles for support capturing backtraces.
//! Some platforms simply do nothing when capturing a backtrace. To check
//! whether the platform supports capturing backtraces you can consult the
//! `BacktraceStatus` enum as a result of `Backtrace::status`.
//!
//! Like above with accuracy platform support is done on a best effort basis.
//! Sometimes libraries may not be available at runtime or something may go
//! wrong which would cause a backtrace to not be captured. Please feel free to
//! report issues with platforms where a backtrace cannot be captured though!
//!
//! ## Environment Variables
//!
//! The `Backtrace::capture` function may not actually capture a backtrace by
//! default. Its behavior is governed by two environment variables:
//!
//! * `RUST_LIB_BACKTRACE` - if this is set to `0` then `Backtrace::capture`
//!   will never capture a backtrace. Any other value this is set to will enable
//!   `Backtrace::capture`.
//!
//! * `RUST_BACKTRACE` - if `RUST_LIB_BACKTRACE` is not set, then this variable
//!   is consulted with the same rules of `RUST_LIB_BACKTRACE`.
//!
//! * If neither of the above env vars are set, then `Backtrace::capture` will
//!   be disabled.
//!
//! Capturing a backtrace can be a quite expensive runtime operation, so the
//! environment variables allow either forcibly disabling this runtime
//! performance hit or allow selectively enabling it in some programs.
//!
//! Note that the `Backtrace::force_capture` function can be used to ignore
//! these environment variables. Also note that the state of environment
//! variables is cached once the first backtrace is created, so altering
//! `RUST_LIB_BACKTRACE` or `RUST_BACKTRACE` at runtime may not actually change
//! how backtraces are captured.

#![unstable(feature = "backtrace", issue = "53487")]

// NB: A note on resolution of a backtrace:
//
// Backtraces primarily happen in two steps, one is where we actually capture
// the stack backtrace, giving us a list of instruction pointers corresponding
// to stack frames. Next we take these instruction pointers and, one-by-one,
// turn them into a human readable name (like `main`).
//
// The first phase can be somewhat expensive (walking the stack), especially
// on MSVC where debug information is consulted to return inline frames each as
// their own frame. The second phase, however, is almost always extremely
// expensive (on the order of milliseconds sometimes) when it's consulting debug
// information.
//
// We attempt to amortize this cost as much as possible by delaying resolution
// of an address to a human readable name for as long as possible. When
// `Backtrace::create` is called to capture a backtrace it doesn't actually
// perform any symbol resolution, but rather we lazily resolve symbols only just
// before they're needed for printing. This way we can make capturing a
// backtrace and throwing it away much cheaper, but actually printing a
// backtrace is still basically the same cost.
//
// This strategy comes at the cost of some synchronization required inside of a
// `Backtrace`, but that's a relatively small price to pay relative to capturing
// a backtrace or actually symbolizing it.

use crate::env;
use crate::fmt;
use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
use crate::sync::Mutex;
use crate::sys_common::backtrace::{lock, output_filename};
use crate::vec::Vec;
use backtrace::BytesOrWideString;
use backtrace_rs as backtrace;

/// A captured OS thread stack backtrace.
///
/// This type represents a stack backtrace for an OS thread captured at a
/// previous point in time. In some instances the `Backtrace` type may
/// internally be empty due to configuration. For more information see
/// `Backtrace::capture`.
pub struct Backtrace {
    inner: Inner,
}

/// The current status of a backtrace, indicating whether it was captured or
/// whether it is empty for some other reason.
#[non_exhaustive]
#[derive(Debug, PartialEq, Eq)]
pub enum BacktraceStatus {
    /// Capturing a backtrace is not supported, likely because it's not
    /// implemented for the current platform.
    Unsupported,
    /// Capturing a backtrace has been disabled through either the
    /// `RUST_LIB_BACKTRACE` or `RUST_BACKTRACE` environment variables.
    Disabled,
    /// A backtrace has been captured and the `Backtrace` should print
    /// reasonable information when rendered.
    Captured,
}

enum Inner {
    Unsupported,
    Disabled,
    Captured(Mutex<Capture>),
}

struct Capture {
    actual_start: usize,
    resolved: bool,
    frames: Vec<BacktraceFrame>,
}

fn _assert_send_sync() {
    fn _assert<T: Send + Sync>() {}
    _assert::<Backtrace>();
}

struct BacktraceFrame {
    frame: backtrace::Frame,
    symbols: Vec<BacktraceSymbol>,
}

struct BacktraceSymbol {
    name: Option<Vec<u8>>,
    filename: Option<BytesOrWide>,
    lineno: Option<u32>,
}

enum BytesOrWide {
    Bytes(Vec<u8>),
    Wide(Vec<u16>),
}

impl fmt::Debug for Backtrace {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut capture = match &self.inner {
            Inner::Unsupported => return fmt.write_str("unsupported backtrace"),
            Inner::Disabled => return fmt.write_str("disabled backtrace"),
            Inner::Captured(c) => c.lock().unwrap(),
        };
        capture.resolve();

        write!(fmt, "Backtrace ")?;

        let mut dbg = fmt.debug_list();

        for frame in &capture.frames {
            dbg.entries(&frame.symbols);
        }

        dbg.finish()
    }
}

impl fmt::Debug for BacktraceSymbol {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut dbg = fmt.debug_struct("");

        if let Some(fn_name) = self.name.as_ref().map(|b| backtrace::SymbolName::new(b)) {
            dbg.field("fn", &fn_name);
        } else {
            dbg.field("fn", &"<unknown>");
        }

        if let Some(fname) = self.filename.as_ref() {
            dbg.field("file", fname);
        }

        if let Some(line) = self.lineno.as_ref() {
            dbg.field("line", line);
        }

        dbg.finish()
    }
}

impl fmt::Debug for BytesOrWide {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        output_filename(
            fmt,
            match self {
                BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w),
                BytesOrWide::Wide(w) => BytesOrWideString::Wide(w),
            },
            backtrace::PrintFmt::Full,
            crate::env::current_dir().as_ref().ok(),
        )
    }
}

impl Backtrace {
    /// Returns whether backtrace captures are enabled through environment
    /// variables.
    fn enabled() -> bool {
        // Cache the result of reading the environment variables to make
        // backtrace captures speedy, because otherwise reading environment
        // variables every time can be somewhat slow.
        static ENABLED: AtomicUsize = AtomicUsize::new(0);
        match ENABLED.load(SeqCst) {
            0 => {}
            1 => return false,
            _ => return true,
        }
        let enabled = match env::var("RUST_LIB_BACKTRACE") {
            Ok(s) => s != "0",
            Err(_) => match env::var("RUST_BACKTRACE") {
                Ok(s) => s != "0",
                Err(_) => false,
            },
        };
        ENABLED.store(enabled as usize + 1, SeqCst);
        return enabled;
    }

    /// Capture a stack backtrace of the current thread.
    ///
    /// This function will capture a stack backtrace of the current OS thread of
    /// execution, returning a `Backtrace` type which can be later used to print
    /// the entire stack trace or render it to a string.
    ///
    /// This function will be a noop if the `RUST_BACKTRACE` or
    /// `RUST_LIB_BACKTRACE` backtrace variables are both not set. If either
    /// environment variable is set and enabled then this function will actually
    /// capture a backtrace. Capturing a backtrace can be both memory intensive
    /// and slow, so these environment variables allow liberally using
    /// `Backtrace::capture` and only incurring a slowdown when the environment
    /// variables are set.
    ///
    /// To forcibly capture a backtrace regardless of environment variables, use
    /// the `Backtrace::force_capture` function.
    #[inline(never)] // want to make sure there's a frame here to remove
    pub fn capture() -> Backtrace {
        if !Backtrace::enabled() {
            return Backtrace { inner: Inner::Disabled };
        }
        Backtrace::create(Backtrace::capture as usize)
    }

    /// Forcibly captures a full backtrace, regardless of environment variable
    /// configuration.
    ///
    /// This function behaves the same as `capture` except that it ignores the
    /// values of the `RUST_BACKTRACE` and `RUST_LIB_BACKTRACE` environment
    /// variables, always capturing a backtrace.
    ///
    /// Note that capturing a backtrace can be an expensive operation on some
    /// platforms, so this should be used with caution in performance-sensitive
    /// parts of code.
    #[inline(never)] // want to make sure there's a frame here to remove
    pub fn force_capture() -> Backtrace {
        Backtrace::create(Backtrace::force_capture as usize)
    }

    // Capture a backtrace which start just before the function addressed by
    // `ip`
    fn create(ip: usize) -> Backtrace {
        let _lock = lock();
        let mut frames = Vec::new();
        let mut actual_start = None;
        unsafe {
            backtrace::trace_unsynchronized(|frame| {
                frames.push(BacktraceFrame { frame: frame.clone(), symbols: Vec::new() });
                if frame.symbol_address() as usize == ip && actual_start.is_none() {
                    actual_start = Some(frames.len());
                }
                true
            });
        }

        // If no frames came out assume that this is an unsupported platform
        // since `backtrace` doesn't provide a way of learning this right now,
        // and this should be a good enough approximation.
        let inner = if frames.len() == 0 {
            Inner::Unsupported
        } else {
            Inner::Captured(Mutex::new(Capture {
                actual_start: actual_start.unwrap_or(0),
                frames,
                resolved: false,
            }))
        };

        Backtrace { inner }
    }

    /// Returns the status of this backtrace, indicating whether this backtrace
    /// request was unsupported, disabled, or a stack trace was actually
    /// captured.
    pub fn status(&self) -> BacktraceStatus {
        match self.inner {
            Inner::Unsupported => BacktraceStatus::Unsupported,
            Inner::Disabled => BacktraceStatus::Disabled,
            Inner::Captured(_) => BacktraceStatus::Captured,
        }
    }
}

impl fmt::Display for Backtrace {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut capture = match &self.inner {
            Inner::Unsupported => return fmt.write_str("unsupported backtrace"),
            Inner::Disabled => return fmt.write_str("disabled backtrace"),
            Inner::Captured(c) => c.lock().unwrap(),
        };
        capture.resolve();

        let full = fmt.alternate();
        let (frames, style) = if full {
            (&capture.frames[..], backtrace::PrintFmt::Full)
        } else {
            (&capture.frames[capture.actual_start..], backtrace::PrintFmt::Short)
        };

        // When printing paths we try to strip the cwd if it exists, otherwise
        // we just print the path as-is. Note that we also only do this for the
        // short format, because if it's full we presumably want to print
        // everything.
        let cwd = crate::env::current_dir();
        let mut print_path = move |fmt: &mut fmt::Formatter<'_>, path: BytesOrWideString<'_>| {
            output_filename(fmt, path, style, cwd.as_ref().ok())
        };

        let mut f = backtrace::BacktraceFmt::new(fmt, style, &mut print_path);
        f.add_context()?;
        for frame in frames {
            let mut f = f.frame();
            if frame.symbols.is_empty() {
                f.print_raw(frame.frame.ip(), None, None, None)?;
            } else {
                for symbol in frame.symbols.iter() {
                    f.print_raw(
                        frame.frame.ip(),
                        symbol.name.as_ref().map(|b| backtrace::SymbolName::new(b)),
                        symbol.filename.as_ref().map(|b| match b {
                            BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w),
                            BytesOrWide::Wide(w) => BytesOrWideString::Wide(w),
                        }),
                        symbol.lineno,
                    )?;
                }
            }
        }
        f.finish()?;
        Ok(())
    }
}

impl Capture {
    fn resolve(&mut self) {
        // If we're already resolved, nothing to do!
        if self.resolved {
            return;
        }
        self.resolved = true;

        // Use the global backtrace lock to synchronize this as it's a
        // requirement of the `backtrace` crate, and then actually resolve
        // everything.
        let _lock = lock();
        for frame in self.frames.iter_mut() {
            let symbols = &mut frame.symbols;
            unsafe {
                backtrace::resolve_frame_unsynchronized(&frame.frame, |symbol| {
                    symbols.push(BacktraceSymbol {
                        name: symbol.name().map(|m| m.as_bytes().to_vec()),
                        filename: symbol.filename_raw().map(|b| match b {
                            BytesOrWideString::Bytes(b) => BytesOrWide::Bytes(b.to_owned()),
                            BytesOrWideString::Wide(b) => BytesOrWide::Wide(b.to_owned()),
                        }),
                        lineno: symbol.lineno(),
                    });
                });
            }
        }
    }
}

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

    #[test]
    fn debug_backtrace_fmt() {
        let bt = Backtrace::capture();
        eprintln!("uncaptured: {:?}", bt);
        let bt = Backtrace::force_capture();
        eprintln!("captured: {:?}", bt);
        eprintln!("display print: {}", bt);
        eprintln!("resolved: {:?}", bt);
        unimplemented!();
    }
}
<|endoftext|>


<commit_before>//
// Copyright (c) Pirmin Kalberer. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

//! Encode geometries according to MVT spec
//! https://github.com/mapbox/vector-tile-spec/tree/master/2.1

use std::vec::Vec;
use core::screen;

/// Command to be executed and the number of times that the command will be executed
/// https://github.com/mapbox/vector-tile-spec/tree/master/2.1#431-command-integers
struct CommandInteger(u32);

enum Command {
    MoveTo    = 1,
    LineTo    = 2,
    ClosePath = 7,
}

impl CommandInteger {
    fn new(id: Command, count: u32) -> CommandInteger {
        CommandInteger(((id as u32) & 0x7) | (count << 3))
    }

    fn id(&self) -> u32 {
        self.0 & 0x7
    }

    fn count(&self) -> u32 {
        self.0 >> 3
    }
}

#[test]
fn test_commands() {
    assert_eq!(CommandInteger(9).id(), Command::MoveTo as u32);
    assert_eq!(CommandInteger(9).count(), 1);

    assert_eq!(CommandInteger::new(Command::MoveTo, 1).0, 9);
    assert_eq!(CommandInteger::new(Command::LineTo, 3).0, 26);
    assert_eq!(CommandInteger::new(Command::ClosePath, 1).0, 15);
}

/// Commands requiring parameters are followed by a ParameterInteger for each parameter required by that command
/// https://github.com/mapbox/vector-tile-spec/tree/master/2.1#432-parameter-integers
struct ParameterInteger(u32);

impl ParameterInteger {
    fn new(value: i32) -> ParameterInteger {
        ParameterInteger(((value << 1) ^ (value >> 31)) as u32)
    }

    fn value(&self) -> i32 {
        ((self.0 >> 1) as i32) ^ (-((self.0 & 1) as i32))
    }
}

#[test]
fn test_paremeters() {
    assert_eq!(ParameterInteger(50).value(), 25);
    assert_eq!(ParameterInteger::new(25).value(), 25);
}

pub struct CommandSequence(Vec<u32>);

impl CommandSequence {
    fn new() -> CommandSequence {
        CommandSequence(Vec::new())
    }
    pub fn vec(&self) -> Vec<u32> {
        self.0.clone() // FIXME: ref
    }
    fn append(&mut self, other: &mut CommandSequence) {
        self.0.append(&mut other.0);
    }
    fn push(&mut self, value: u32) {
        self.0.push(value);
    }
}

pub trait EncodableGeom {
    fn encode_from(&self, startpos: &screen::Point) -> CommandSequence;
    fn encode(&self) -> CommandSequence {
        self.encode_from(&screen::Point::origin())
    }
}

impl EncodableGeom for screen::Point {
    fn encode_from(&self, startpos: &screen::Point) -> CommandSequence {
        CommandSequence(vec![
            CommandInteger::new(Command::MoveTo, 1).0,
            ParameterInteger::new(self.x - startpos.x).0,
            ParameterInteger::new(self.y - startpos.y).0
        ])
    }
}

impl EncodableGeom for screen::MultiPoint {
    fn encode_from(&self, startpos: &screen::Point) -> CommandSequence {
        let mut seq = CommandSequence::new();
        seq.push(CommandInteger::new(
            Command::MoveTo, self.points.len() as u32).0);
        let (mut posx, mut posy) = (startpos.x, startpos.y);
        for point in &self.points {
            seq.push(ParameterInteger::new(point.x - posx).0);
            seq.push(ParameterInteger::new(point.y - posy).0);
            posx = point.x;
            posy = point.y;
        }
        seq
    }
}

impl EncodableGeom for screen::LineString {
    fn encode_from(&self, startpos: &screen::Point) -> CommandSequence {
        let mut seq = CommandSequence::new();
        if self.points.len() > 0 {
            seq = self.points[0].encode_from(startpos);
            seq.push(CommandInteger::new(
                Command::LineTo, (self.points.len()-1) as u32).0);
            for i in 1..self.points.len() {
                let ref pos = &self.points[i-1];
                let ref point = &self.points[i];
                seq.push(ParameterInteger::new(point.x - pos.x).0);
                seq.push(ParameterInteger::new(point.y - pos.y).0);
            }
        }
        seq
    }
}
impl screen::LineString {
    fn encode_ring_from(&self, startpos: &screen::Point) -> CommandSequence {
        // almost same as LineString.encode_from, with ClosePath instead of last point
        let mut seq = CommandSequence::new();
        if self.points.len() > 0 {
            seq = self.points[0].encode_from(startpos);
            seq.push(CommandInteger::new(
                Command::LineTo, (self.points.len()-2) as u32).0);
            for i in 1..self.points.len()-1 {
                let ref pos = &self.points[i-1];
                let ref point = &self.points[i];
                seq.push(ParameterInteger::new(point.x - pos.x).0);
                seq.push(ParameterInteger::new(point.y - pos.y).0);
            }
            seq.push(CommandInteger::new(Command::ClosePath, 1).0);
        }
        seq
    }
}

impl EncodableGeom for screen::MultiLineString {
    fn encode_from(&self, startpos: &screen::Point) -> CommandSequence {
        let mut seq = CommandSequence::new();
        let mut pos = startpos;
        for line in &self.lines {
            if line.points.len() > 0 {
                seq.append(&mut line.encode_from(&pos));
                pos = &line.points[line.points.len()-1];
            }
        }
        seq
    }
}

impl EncodableGeom for screen::Polygon {
    fn encode_from(&self, startpos: &screen::Point) -> CommandSequence {
        let mut seq = CommandSequence::new();
        let mut pos = startpos;
        for line in &self.rings {
            if line.points.len() > 1 {
                seq.append(&mut line.encode_ring_from(&pos));
                pos = &line.points[line.points.len()-2];
            }
        }
        seq
    }
}

impl EncodableGeom for screen::MultiPolygon {
    fn encode_from(&self, startpos: &screen::Point) -> CommandSequence {
        let mut seq = CommandSequence::new();
        let mut pos = startpos;
        for polygon in &self.polygons {
            for line in &polygon.rings {
                if line.points.len() > 1 {
                    seq.append(&mut line.encode_ring_from(&pos));
                    pos = &line.points[line.points.len()-2];
                }
            }
        }
        seq
    }
}

#[test]
fn test_geom_encoding() {
    let point = screen::Point { x: 25, y: 17 };
    assert_eq!(point.encode().0, &[9,50,34]);

    let multipoint = screen::MultiPoint {
        points: vec![
            screen::Point { x: 5, y: 7 },
            screen::Point { x: 3, y: 2 }
            ]
        };
    assert_eq!(multipoint.encode().0, &[17,10,14,3,9]);

    let linestring = screen::LineString {
        points: vec![
            screen::Point { x: 2, y: 2 },
            screen::Point { x: 2, y: 10 },
            screen::Point { x: 10, y: 10 }
            ]
        };
    assert_eq!(linestring.encode().0, &[9,4,4,18,0,16,16,0]);

    let multilinestring = screen::MultiLineString {
        lines: vec![
            screen::LineString {
                points: vec![
                    screen::Point { x: 2, y: 2 },
                    screen::Point { x: 2, y: 10 },
                    screen::Point { x: 10, y: 10 }
                    ]
            },
            screen::LineString {
                points: vec![
                    screen::Point { x: 1, y: 1 },
                    screen::Point { x: 3, y: 5 }
                    ]
            }
            ]
        };
    assert_eq!(multilinestring.encode().0, &[9,4,4,18,0,16,16,0,9,17,17,10,4,8]);

    let polygon = screen::Polygon {
        rings: vec![
            screen::LineString {
                points: vec![
                    screen::Point { x: 3, y: 6 },
                    screen::Point { x: 8, y: 12 },
                    screen::Point { x: 20, y: 34 },
                    screen::Point { x: 3, y: 6 }
                    ]
            }
            ]
        };
    assert_eq!(polygon.encode().0, &[9,6,12,18,10,12,24,44,15]);

    let multipolygon = screen::MultiPolygon {
        polygons: vec![
            screen::Polygon {
                rings: vec![
                    screen::LineString {
                        points: vec![
                            screen::Point { x: 0, y: 0 },
                            screen::Point { x: 10, y: 0 },
                            screen::Point { x: 10, y: 10 },
                            screen::Point { x: 0, y: 10 },
                            screen::Point { x: 0, y: 0 }
                            ]
                    }
                    ]
            },
            screen::Polygon {
                rings: vec![
                    screen::LineString {
                        points: vec![
                            screen::Point { x: 11, y: 11 },
                            screen::Point { x: 20, y: 11 },
                            screen::Point { x: 20, y: 20 },
                            screen::Point { x: 11, y: 20 },
                            screen::Point { x: 11, y: 20 },
                            screen::Point { x: 11, y: 11 }
                            ]
                    },
                    screen::LineString {
                        points: vec![
                            screen::Point { x: 13, y: 13 },
                            screen::Point { x: 13, y: 17 },
                            screen::Point { x: 17, y: 17 },
                            screen::Point { x: 17, y: 13 },
                            screen::Point { x: 13, y: 13 }
                            ]
                    }
                    ]
            }
            ]
        };
    let expected = [9,0,0,26,20,0,0,20,19,0,15,9,22,2,34,18,0,0,18,17,0,0,0,15,9,4,13,26,0,8,8,0,0,7,15];
    assert_eq!(multipolygon.encode().0, &expected[0..35]);
}
<commit_msg>Avoid appending vectors in geometry encoding<commit_after>//
// Copyright (c) Pirmin Kalberer. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

//! Encode geometries according to MVT spec
//! https://github.com/mapbox/vector-tile-spec/tree/master/2.1

use std::vec::Vec;
use core::screen;

/// Command to be executed and the number of times that the command will be executed
/// https://github.com/mapbox/vector-tile-spec/tree/master/2.1#431-command-integers
struct CommandInteger(u32);

enum Command {
    MoveTo    = 1,
    LineTo    = 2,
    ClosePath = 7,
}

impl CommandInteger {
    fn new(id: Command, count: u32) -> CommandInteger {
        CommandInteger(((id as u32) & 0x7) | (count << 3))
    }

    fn id(&self) -> u32 {
        self.0 & 0x7
    }

    fn count(&self) -> u32 {
        self.0 >> 3
    }
}

#[test]
fn test_commands() {
    assert_eq!(CommandInteger(9).id(), Command::MoveTo as u32);
    assert_eq!(CommandInteger(9).count(), 1);

    assert_eq!(CommandInteger::new(Command::MoveTo, 1).0, 9);
    assert_eq!(CommandInteger::new(Command::LineTo, 3).0, 26);
    assert_eq!(CommandInteger::new(Command::ClosePath, 1).0, 15);
}

/// Commands requiring parameters are followed by a ParameterInteger for each parameter required by that command
/// https://github.com/mapbox/vector-tile-spec/tree/master/2.1#432-parameter-integers
struct ParameterInteger(u32);

impl ParameterInteger {
    fn new(value: i32) -> ParameterInteger {
        ParameterInteger(((value << 1) ^ (value >> 31)) as u32)
    }

    fn value(&self) -> i32 {
        ((self.0 >> 1) as i32) ^ (-((self.0 & 1) as i32))
    }
}

#[test]
fn test_paremeters() {
    assert_eq!(ParameterInteger(50).value(), 25);
    assert_eq!(ParameterInteger::new(25).value(), 25);
}

pub struct CommandSequence(Vec<u32>);

impl CommandSequence {
    fn new() -> CommandSequence {
        CommandSequence(Vec::new())
    }
    pub fn vec(&self) -> Vec<u32> {
        self.0.clone() // FIXME: ref
    }
    fn append(&mut self, other: &mut CommandSequence) {
        self.0.append(&mut other.0);
    }
    fn push(&mut self, value: u32) {
        self.0.push(value);
    }
}

pub trait EncodableGeom {
    fn encode(&self) -> CommandSequence {
        let mut seq = CommandSequence::new();
        self.encode_from(&screen::Point::origin(), &mut seq);
        seq
    }
    fn encode_from(&self, startpos: &screen::Point, seq: &mut CommandSequence);
}

impl EncodableGeom for screen::Point {
    fn encode_from(&self, startpos: &screen::Point, seq: &mut CommandSequence) {
        seq.push(CommandInteger::new(
            Command::MoveTo, 1).0);
        seq.push(ParameterInteger::new(self.x - startpos.x).0);
        seq.push(ParameterInteger::new(self.y - startpos.y).0);
    }
}

impl EncodableGeom for screen::MultiPoint {
    fn encode_from(&self, startpos: &screen::Point, seq: &mut CommandSequence) {
        seq.push(CommandInteger::new(
            Command::MoveTo, self.points.len() as u32).0);
        let (mut posx, mut posy) = (startpos.x, startpos.y);
        for point in &self.points {
            seq.push(ParameterInteger::new(point.x - posx).0);
            seq.push(ParameterInteger::new(point.y - posy).0);
            posx = point.x;
            posy = point.y;
        }
    }
}

impl EncodableGeom for screen::LineString {
    fn encode_from(&self, startpos: &screen::Point, seq: &mut CommandSequence) {
        if self.points.len() > 0 {
            self.points[0].encode_from(startpos, seq);
            seq.push(CommandInteger::new(
                Command::LineTo, (self.points.len()-1) as u32).0);
            for i in 1..self.points.len() {
                let ref pos = &self.points[i-1];
                let ref point = &self.points[i];
                seq.push(ParameterInteger::new(point.x - pos.x).0);
                seq.push(ParameterInteger::new(point.y - pos.y).0);
            }
        }
    }
}
impl screen::LineString {
    fn encode_ring_from(&self, startpos: &screen::Point, seq: &mut CommandSequence) {
        // almost same as LineString.encode_from, with ClosePath instead of last point
        if self.points.len() > 0 {
            self.points[0].encode_from(startpos, seq);
            seq.push(CommandInteger::new(
                Command::LineTo, (self.points.len()-2) as u32).0);
            for i in 1..self.points.len()-1 {
                let ref pos = &self.points[i-1];
                let ref point = &self.points[i];
                seq.push(ParameterInteger::new(point.x - pos.x).0);
                seq.push(ParameterInteger::new(point.y - pos.y).0);
            }
            seq.push(CommandInteger::new(Command::ClosePath, 1).0);
        }
    }
}

impl EncodableGeom for screen::MultiLineString {
    fn encode_from(&self, startpos: &screen::Point, seq: &mut CommandSequence) {
        let mut pos = startpos;
        for line in &self.lines {
            if line.points.len() > 0 {
                line.encode_from(&pos, seq);
                pos = &line.points[line.points.len()-1];
            }
        }
    }
}

impl EncodableGeom for screen::Polygon {
    fn encode_from(&self, startpos: &screen::Point, seq: &mut CommandSequence) {
        let mut pos = startpos;
        for line in &self.rings {
            if line.points.len() > 1 {
                line.encode_ring_from(&pos, seq);
                pos = &line.points[line.points.len()-2];
            }
        }
    }
}

impl EncodableGeom for screen::MultiPolygon {
    fn encode_from(&self, startpos: &screen::Point, seq: &mut CommandSequence) {
        let mut pos = startpos;
        for polygon in &self.polygons {
            for line in &polygon.rings {
                if line.points.len() > 1 {
                    line.encode_ring_from(&pos, seq);
                    pos = &line.points[line.points.len()-2];
                }
            }
        }
    }
}

#[test]
fn test_geom_encoding() {
    let point = screen::Point { x: 25, y: 17 };
    assert_eq!(point.encode().0, &[9,50,34]);

    let multipoint = screen::MultiPoint {
        points: vec![
            screen::Point { x: 5, y: 7 },
            screen::Point { x: 3, y: 2 }
            ]
        };
    assert_eq!(multipoint.encode().0, &[17,10,14,3,9]);

    let linestring = screen::LineString {
        points: vec![
            screen::Point { x: 2, y: 2 },
            screen::Point { x: 2, y: 10 },
            screen::Point { x: 10, y: 10 }
            ]
        };
    assert_eq!(linestring.encode().0, &[9,4,4,18,0,16,16,0]);

    let multilinestring = screen::MultiLineString {
        lines: vec![
            screen::LineString {
                points: vec![
                    screen::Point { x: 2, y: 2 },
                    screen::Point { x: 2, y: 10 },
                    screen::Point { x: 10, y: 10 }
                    ]
            },
            screen::LineString {
                points: vec![
                    screen::Point { x: 1, y: 1 },
                    screen::Point { x: 3, y: 5 }
                    ]
            }
            ]
        };
    assert_eq!(multilinestring.encode().0, &[9,4,4,18,0,16,16,0,9,17,17,10,4,8]);

    let polygon = screen::Polygon {
        rings: vec![
            screen::LineString {
                points: vec![
                    screen::Point { x: 3, y: 6 },
                    screen::Point { x: 8, y: 12 },
                    screen::Point { x: 20, y: 34 },
                    screen::Point { x: 3, y: 6 }
                    ]
            }
            ]
        };
    assert_eq!(polygon.encode().0, &[9,6,12,18,10,12,24,44,15]);

    let multipolygon = screen::MultiPolygon {
        polygons: vec![
            screen::Polygon {
                rings: vec![
                    screen::LineString {
                        points: vec![
                            screen::Point { x: 0, y: 0 },
                            screen::Point { x: 10, y: 0 },
                            screen::Point { x: 10, y: 10 },
                            screen::Point { x: 0, y: 10 },
                            screen::Point { x: 0, y: 0 }
                            ]
                    }
                    ]
            },
            screen::Polygon {
                rings: vec![
                    screen::LineString {
                        points: vec![
                            screen::Point { x: 11, y: 11 },
                            screen::Point { x: 20, y: 11 },
                            screen::Point { x: 20, y: 20 },
                            screen::Point { x: 11, y: 20 },
                            screen::Point { x: 11, y: 20 },
                            screen::Point { x: 11, y: 11 }
                            ]
                    },
                    screen::LineString {
                        points: vec![
                            screen::Point { x: 13, y: 13 },
                            screen::Point { x: 13, y: 17 },
                            screen::Point { x: 17, y: 17 },
                            screen::Point { x: 17, y: 13 },
                            screen::Point { x: 13, y: 13 }
                            ]
                    }
                    ]
            }
            ]
        };
    let expected = [9,0,0,26,20,0,0,20,19,0,15,9,22,2,34,18,0,0,18,17,0,0,0,15,9,4,13,26,0,8,8,0,0,7,15];
    assert_eq!(multipolygon.encode().0, &expected[0..35]);
}
<|endoftext|>


<commit_before>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! The proof of work needs to strike a balance between fast header
//! verification to avoid DoS attacks and difficulty for block verifiers to
//! build new blocks. In addition, mining new blocks should also be as
//! difficult on high end custom-made hardware (ASICs) as on commodity hardware
//! or smartphones. For this reason we use Cuckoo Cycle (see the cuckoo
//! module for more information).
//!
//! Note that this miner implementation is here mostly for tests and
//! reference. It's not optimized for speed.

#![deny(non_upper_case_globals)]
#![deny(non_camel_case_types)]
#![deny(non_snake_case)]
#![deny(unused_mut)]
#![warn(missing_docs)]

extern crate blake2_rfc as blake2;
extern crate chrono;
extern crate num;
extern crate rand;
extern crate serde;

extern crate grin_util as util;

#[macro_use]
mod common;
pub mod cuckaroo;
pub mod cuckatoo;
mod error;
#[allow(dead_code)]
pub mod lean;
mod siphash;
mod types;

use chrono::prelude::{DateTime, NaiveDateTime, Utc};
use core::{Block, BlockHeader};
use genesis;
use global;

pub use self::common::EdgeType;
pub use self::types::*;
pub use pow::cuckaroo::{new_cuckaroo_ctx, CuckarooContext};
pub use pow::cuckatoo::{new_cuckatoo_ctx, CuckatooContext};
pub use pow::error::Error;

const MAX_SOLS: u32 = 10;

/// Validates the proof of work of a given header, and that the proof of work
/// satisfies the requirements of the header.
pub fn verify_size(bh: &BlockHeader) -> Result<(), Error> {
	let mut ctx = global::create_pow_context::<u64>(
		bh.height,
		bh.pow.edge_bits(),
		bh.pow.proof.nonces.len(),
		MAX_SOLS,
	)?;
	ctx.set_header_nonce(bh.pre_pow(), None, false)?;
	ctx.verify(&bh.pow.proof)
}

/// Mines a genesis block using the internal miner
pub fn mine_genesis_block() -> Result<Block, Error> {
	let mut gen = genesis::genesis_testnet2();
	if global::is_user_testing_mode() || global::is_automated_testing_mode() {
		gen = genesis::genesis_dev();
		gen.header.timestamp = Utc::now();
	}

	// total_difficulty on the genesis header *is* the difficulty of that block
	let genesis_difficulty = gen.header.pow.total_difficulty;

	let sz = global::min_edge_bits();
	let proof_size = global::proofsize();

	pow_size(&mut gen.header, genesis_difficulty, proof_size, sz)?;
	Ok(gen)
}

/// Runs a proof of work computation over the provided block using the provided
/// Mining Worker, until the required difficulty target is reached. May take a
/// while for a low target...
pub fn pow_size(
	bh: &mut BlockHeader,
	diff: Difficulty,
	proof_size: usize,
	sz: u8,
) -> Result<(), Error> {
	let start_nonce = bh.pow.nonce;

	// set the nonce for faster solution finding in user testing
	if bh.height == 0 && global::is_user_testing_mode() {
		bh.pow.nonce = global::get_genesis_nonce();
	}

	// try to find a cuckoo cycle on that header hash
	loop {
		// if we found a cycle (not guaranteed) and the proof hash is higher that the
		// diff, we're all good
		let mut ctx = global::create_pow_context::<u32>(bh.height, sz, proof_size, MAX_SOLS)?;
		ctx.set_header_nonce(bh.pre_pow(), None, true)?;
		if let Ok(proofs) = ctx.find_cycles() {
			bh.pow.proof = proofs[0].clone();
			if bh.pow.to_difficulty() >= diff {
				return Ok(());
			}
		}

		// otherwise increment the nonce
		let (res, _) = bh.pow.nonce.overflowing_add(1);
		bh.pow.nonce = res;

		// and if we're back where we started, update the time (changes the hash as
		// well)
		if bh.pow.nonce == start_nonce {
			bh.timestamp = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(0, 0), Utc);
		}
	}
}

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

	/// We'll be generating genesis blocks differently
	#[ignore]
	#[test]
	fn genesis_pow() {
		let mut b = genesis::genesis_dev();
		b.header.pow.nonce = 485;
		b.header.pow.proof.edge_bits = global::min_edge_bits();
		pow_size(
			&mut b.header,
			Difficulty::min(),
			global::proofsize(),
			global::min_edge_bits(),
		).unwrap();
		assert!(b.header.pow.nonce != 310);
		assert!(b.header.pow.to_difficulty() >= Difficulty::min());
		assert!(verify_size(&b.header).is_ok());
	}
}
<commit_msg>Fixing disabled unit test pow::test::genesis_pow (#1984)<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! The proof of work needs to strike a balance between fast header
//! verification to avoid DoS attacks and difficulty for block verifiers to
//! build new blocks. In addition, mining new blocks should also be as
//! difficult on high end custom-made hardware (ASICs) as on commodity hardware
//! or smartphones. For this reason we use Cuckoo Cycle (see the cuckoo
//! module for more information).
//!
//! Note that this miner implementation is here mostly for tests and
//! reference. It's not optimized for speed.

#![deny(non_upper_case_globals)]
#![deny(non_camel_case_types)]
#![deny(non_snake_case)]
#![deny(unused_mut)]
#![warn(missing_docs)]

extern crate blake2_rfc as blake2;
extern crate chrono;
extern crate num;
extern crate rand;
extern crate serde;

extern crate grin_util as util;

#[macro_use]
mod common;
pub mod cuckaroo;
pub mod cuckatoo;
mod error;
#[allow(dead_code)]
pub mod lean;
mod siphash;
mod types;

use chrono::prelude::{DateTime, NaiveDateTime, Utc};
use core::{Block, BlockHeader};
use genesis;
use global;

pub use self::common::EdgeType;
pub use self::types::*;
pub use pow::cuckaroo::{new_cuckaroo_ctx, CuckarooContext};
pub use pow::cuckatoo::{new_cuckatoo_ctx, CuckatooContext};
pub use pow::error::Error;

const MAX_SOLS: u32 = 10;

/// Validates the proof of work of a given header, and that the proof of work
/// satisfies the requirements of the header.
pub fn verify_size(bh: &BlockHeader) -> Result<(), Error> {
	let mut ctx = global::create_pow_context::<u64>(
		bh.height,
		bh.pow.edge_bits(),
		bh.pow.proof.nonces.len(),
		MAX_SOLS,
	)?;
	ctx.set_header_nonce(bh.pre_pow(), None, false)?;
	ctx.verify(&bh.pow.proof)
}

/// Mines a genesis block using the internal miner
pub fn mine_genesis_block() -> Result<Block, Error> {
	let mut gen = genesis::genesis_testnet2();
	if global::is_user_testing_mode() || global::is_automated_testing_mode() {
		gen = genesis::genesis_dev();
		gen.header.timestamp = Utc::now();
	}

	// total_difficulty on the genesis header *is* the difficulty of that block
	let genesis_difficulty = gen.header.pow.total_difficulty;

	let sz = global::min_edge_bits();
	let proof_size = global::proofsize();

	pow_size(&mut gen.header, genesis_difficulty, proof_size, sz)?;
	Ok(gen)
}

/// Runs a proof of work computation over the provided block using the provided
/// Mining Worker, until the required difficulty target is reached. May take a
/// while for a low target...
pub fn pow_size(
	bh: &mut BlockHeader,
	diff: Difficulty,
	proof_size: usize,
	sz: u8,
) -> Result<(), Error> {
	let start_nonce = bh.pow.nonce;

	// set the nonce for faster solution finding in user testing
	if bh.height == 0 && global::is_user_testing_mode() {
		bh.pow.nonce = global::get_genesis_nonce();
	}

	// try to find a cuckoo cycle on that header hash
	loop {
		// if we found a cycle (not guaranteed) and the proof hash is higher that the
		// diff, we're all good
		let mut ctx = global::create_pow_context::<u32>(bh.height, sz, proof_size, MAX_SOLS)?;
		ctx.set_header_nonce(bh.pre_pow(), None, true)?;
		if let Ok(proofs) = ctx.find_cycles() {
			bh.pow.proof = proofs[0].clone();
			if bh.pow.to_difficulty() >= diff {
				return Ok(());
			}
		}

		// otherwise increment the nonce
		let (res, _) = bh.pow.nonce.overflowing_add(1);
		bh.pow.nonce = res;

		// and if we're back where we started, update the time (changes the hash as
		// well)
		if bh.pow.nonce == start_nonce {
			bh.timestamp = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(0, 0), Utc);
		}
	}
}

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

	/// We'll be generating genesis blocks differently
	#[test]
	fn genesis_pow() {
		global::set_mining_mode(ChainTypes::AutomatedTesting);

		let mut b = genesis::genesis_dev();
		b.header.pow.nonce = 485;
		b.header.pow.proof.edge_bits = global::min_edge_bits();
		pow_size(
			&mut b.header,
			Difficulty::min(),
			global::proofsize(),
			global::min_edge_bits(),
		).unwrap();
		assert_ne!(b.header.pow.nonce, 310);
		assert!(b.header.pow.to_difficulty() >= Difficulty::min());
		assert!(verify_size(&b.header).is_ok());
	}
}
<|endoftext|>


<commit_before>use std::num::{Zero, One};
use nalgebra::na::{AlgebraicVecExt, Cast, Identity, Translation, Rotate, Transform};
use nalgebra::na;
use narrow::algorithm::simplex::Simplex;
use narrow::algorithm::johnson_simplex::JohnsonSimplex;
use geom::{Cylinder, Cone, Capsule, MinkowskiSum, Implicit};
use ray::{Ray, RayCast, RayCastWithTransform};
use ray;

/// Projects the origin on a geometry unsing the GJK algorithm.
///
/// # Arguments:
///     * geom - the geometry to project the origin on
///     * simplex - the simplex to be used by the GJK algorithm. It must be already initialized
///     with at least one point on the geometry boundary.
pub fn gjk_toi_and_normal_with_ray<S: Simplex<N, V>,
                                   G: Implicit<N, V, M>,
                                   N: Ord + Num + Float + Cast<f32>,
                                   V: AlgebraicVecExt<N> + Clone,
                                   M: Translation<V>>(
                                   m:       &M,
                                   geom:    &G,
                                   simplex: &mut S,
                                   ray:     &Ray<V>)
                                   -> Option<(N, V)> {
    let mut ltoi: N = Zero::zero();

    let _eps: N  = Float::epsilon();
    let _eps_tol = _eps * Cast::from(100.0);
    let _eps_rel = _eps.sqrt();
    let _dim     = na::dim::<V>();

    // initialization
    let mut curr_ray   = Ray::new(ray.orig.clone(), ray.dir.clone());
    let mut dir        = curr_ray.orig - m.translation();

    if dir.is_zero() {
        dir.set(0, One::one())
    }

    let mut old_sq_len: N = Bounded::max_value();

    let mut ldir = dir.clone();
    // FIXME: this converges in more than 100 iterations… something is wrong here…
    loop {
        dir.normalize();

        let support_point = geom.support_point(m, &dir);

        // Clip the ray on the support plane (None <=> t < 0)
        // The configurations are:
        //   dir.dot(ray.dir)  |   t   |               Action
        // −−−−−−−−−−−−−−−−−−−−+−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
        //          < 0        |  < 0  | Continue.
        //          < 0        |  > 0  | New lower bound, move the origin.
        //          > 0        |  < 0  | Miss. No intersection.
        //          > 0        |  > 0  | New higher bound.
        match ray::plane_toi_with_ray(&support_point, &dir, &curr_ray) {
            Some(t) => {
                if na::dot(&dir, &ray.dir) < na::zero() {
                    // new lower bound
                    ldir = dir.clone();
                    if false { // t <= _eps_rel * ltoi {
                        return Some((ltoi, dir))
                    }

                    ltoi   = ltoi + t;
                    curr_ray.orig = ray.orig + ray.dir * ltoi;
                    dir    = curr_ray.orig - support_point;
                    simplex.reset(-dir);
                    let _M: N = Bounded::max_value();
                    old_sq_len = _M;
                    continue
                }
            },
            None => {
                if na::dot(&dir, &ray.dir) > na::zero() {
                    // miss
                    return None
                }
            }
        }

        simplex.add_point(support_point - curr_ray.orig);

        let proj = simplex.project_origin_and_reduce();
        let sq_len_dir = na::sqnorm(&proj);

        if (simplex.dimension() == _dim ||
            sq_len_dir >= old_sq_len    || // FIXME: hacky way to prevent infinite loop…
            sq_len_dir <= _eps_tol * simplex.max_sq_len()
           ) {
            return Some((ltoi, ldir)) // FIXME: dir or -proj ?
        }

        old_sq_len = sq_len_dir;
        dir        = -proj;
    }
}

impl<N: Ord + Num + Float + Cast<f32> + Clone,
     V: AlgebraicVecExt<N> + Clone>
RayCast<N, V> for Cylinder<N> {
    fn toi_and_normal_with_ray(&self, ray: &Ray<V>) -> Option<(N, V)> {
        gjk_toi_and_normal_with_ray(&Identity::new(), self, &mut JohnsonSimplex::<N, V>::new_w_tls(), ray)
    }
}

impl<N: Ord + Num + Float + Cast<f32> + Clone,
     V: AlgebraicVecExt<N> + Clone,
     M: Transform<V> + Rotate<V>>
RayCastWithTransform<N, V, M> for Cylinder<N> { }

impl<N: Ord + Num + Float + Cast<f32> + Clone,
     V: AlgebraicVecExt<N> + Clone>
RayCast<N, V> for Cone<N> {
    fn toi_and_normal_with_ray(&self, ray: &Ray<V>) -> Option<(N, V)> {
        gjk_toi_and_normal_with_ray(&Identity::new(), self, &mut JohnsonSimplex::<N, V>::new_w_tls(), ray)
    }
}

impl<N: Ord + Num + Float + Cast<f32> + Clone,
     V: AlgebraicVecExt<N> + Clone,
     M: Transform<V> + Rotate<V>>
RayCastWithTransform<N, V, M> for Cone<N> { }

impl<N: Ord + Num + Float + Cast<f32> + Clone,
     V: AlgebraicVecExt<N> + Clone>
RayCast<N, V> for Capsule<N> {
    fn toi_and_normal_with_ray(&self, ray: &Ray<V>) -> Option<(N, V)> {
        gjk_toi_and_normal_with_ray(&Identity::new(), self, &mut JohnsonSimplex::<N, V>::new_w_tls(), ray)
    }
}

impl<N: Ord + Num + Float + Cast<f32> + Clone,
     V: AlgebraicVecExt<N> + Clone,
     M: Transform<V> + Rotate<V>>
RayCastWithTransform<N, V, M> for Capsule<N> { }

impl<'self,
     N:  Ord + Num + Float + Cast<f32> + Clone,
     V:  AlgebraicVecExt<N> + Clone,
     G1: Implicit<N, V, M>,
     G2: Implicit<N, V, M>,
     M>
RayCast<N, V> for MinkowskiSum<'self, M, G1, G2> {
    fn toi_and_normal_with_ray(&self, ray: &Ray<V>) -> Option<(N, V)> {
        gjk_toi_and_normal_with_ray(&Identity::new(), self, &mut JohnsonSimplex::<N, V>::new_w_tls(), ray)
    }
}

impl<'self,
     N:  Ord + Num + Float + Cast<f32> + Clone,
     V:  AlgebraicVecExt<N> + Clone,
     G1: Implicit<N, V, M>,
     G2: Implicit<N, V, M>,
     M:  Rotate<V> + Transform<V>>
RayCastWithTransform<N, V, M> for MinkowskiSum<'self, M, G1, G2> { }
<commit_msg>Add an approximative stopping condition to the gjk-based ray caster.<commit_after>use std::num::{Zero, One};
use nalgebra::na::{AlgebraicVecExt, Cast, Identity, Translation, Rotate, Transform};
use nalgebra::na;
use narrow::algorithm::simplex::Simplex;
use narrow::algorithm::johnson_simplex::JohnsonSimplex;
use geom::{Cylinder, Cone, Capsule, MinkowskiSum, Implicit};
use ray::{Ray, RayCast, RayCastWithTransform};
use ray;

/// Projects the origin on a geometry unsing the GJK algorithm.
///
/// # Arguments:
///     * geom - the geometry to project the origin on
///     * simplex - the simplex to be used by the GJK algorithm. It must be already initialized
///     with at least one point on the geometry boundary.
pub fn gjk_toi_and_normal_with_ray<S: Simplex<N, V>,
                                   G: Implicit<N, V, M>,
                                   N: Ord + Num + Float + Cast<f32>,
                                   V: AlgebraicVecExt<N> + Clone,
                                   M: Translation<V>>(
                                   m:       &M,
                                   geom:    &G,
                                   simplex: &mut S,
                                   ray:     &Ray<V>)
                                   -> Option<(N, V)> {
    let mut ltoi: N = Zero::zero();

    let _eps: N  = Float::epsilon();
    let _eps_tol = _eps * Cast::from(100.0);
    let _eps_rel = _eps.sqrt();
    let _dim     = na::dim::<V>();

    // initialization
    let mut curr_ray   = Ray::new(ray.orig.clone(), ray.dir.clone());
    let mut dir        = curr_ray.orig - m.translation();

    if dir.is_zero() {
        dir.set(0, One::one())
    }

    let mut old_sq_len: N = Bounded::max_value();

    let mut ldir = dir.clone();
    // FIXME: this converges in more than 100 iterations… something is wrong here…
    loop {
        dir.normalize();

        let support_point = geom.support_point(m, &dir);

        // Clip the ray on the support plane (None <=> t < 0)
        // The configurations are:
        //   dir.dot(ray.dir)  |   t   |               Action
        // −−−−−−−−−−−−−−−−−−−−+−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
        //          < 0        |  < 0  | Continue.
        //          < 0        |  > 0  | New lower bound, move the origin.
        //          > 0        |  < 0  | Miss. No intersection.
        //          > 0        |  > 0  | New higher bound.
        match ray::plane_toi_with_ray(&support_point, &dir, &curr_ray) {
            Some(t) => {
                if na::dot(&dir, &ray.dir) < na::zero() {
                    // new lower bound
                    ldir = dir.clone();
                    // XXX: this prevents the normal from being perfectly continuous.
                    // However, without this the algorithm might never converge…
                    // Find a way to fix that.
                    if t <= _eps_rel * ltoi {
                        return Some((ltoi, dir))
                    }

                    ltoi   = ltoi + t;
                    curr_ray.orig = ray.orig + ray.dir * ltoi;
                    dir    = curr_ray.orig - support_point;
                    simplex.reset(-dir);
                    let _M: N = Bounded::max_value();
                    old_sq_len = _M;
                    continue
                }
            },
            None => {
                if na::dot(&dir, &ray.dir) > na::zero() {
                    // miss
                    return None
                }
            }
        }

        simplex.add_point(support_point - curr_ray.orig);

        let proj = simplex.project_origin_and_reduce();
        let sq_len_dir = na::sqnorm(&proj);

        if (simplex.dimension() == _dim ||
            sq_len_dir >= old_sq_len    || // FIXME: hacky way to prevent infinite loop…
            sq_len_dir <= _eps_tol * simplex.max_sq_len()
           ) {
            return Some((ltoi, ldir)) // FIXME: dir or -proj ?
        }

        old_sq_len = sq_len_dir;
        dir        = -proj;
    }
}

impl<N: Ord + Num + Float + Cast<f32> + Clone,
     V: AlgebraicVecExt<N> + Clone>
RayCast<N, V> for Cylinder<N> {
    fn toi_and_normal_with_ray(&self, ray: &Ray<V>) -> Option<(N, V)> {
        gjk_toi_and_normal_with_ray(&Identity::new(), self, &mut JohnsonSimplex::<N, V>::new_w_tls(), ray)
    }
}

impl<N: Ord + Num + Float + Cast<f32> + Clone,
     V: AlgebraicVecExt<N> + Clone,
     M: Transform<V> + Rotate<V>>
RayCastWithTransform<N, V, M> for Cylinder<N> { }

impl<N: Ord + Num + Float + Cast<f32> + Clone,
     V: AlgebraicVecExt<N> + Clone>
RayCast<N, V> for Cone<N> {
    fn toi_and_normal_with_ray(&self, ray: &Ray<V>) -> Option<(N, V)> {
        gjk_toi_and_normal_with_ray(&Identity::new(), self, &mut JohnsonSimplex::<N, V>::new_w_tls(), ray)
    }
}

impl<N: Ord + Num + Float + Cast<f32> + Clone,
     V: AlgebraicVecExt<N> + Clone,
     M: Transform<V> + Rotate<V>>
RayCastWithTransform<N, V, M> for Cone<N> { }

impl<N: Ord + Num + Float + Cast<f32> + Clone,
     V: AlgebraicVecExt<N> + Clone>
RayCast<N, V> for Capsule<N> {
    fn toi_and_normal_with_ray(&self, ray: &Ray<V>) -> Option<(N, V)> {
        gjk_toi_and_normal_with_ray(&Identity::new(), self, &mut JohnsonSimplex::<N, V>::new_w_tls(), ray)
    }
}

impl<N: Ord + Num + Float + Cast<f32> + Clone,
     V: AlgebraicVecExt<N> + Clone,
     M: Transform<V> + Rotate<V>>
RayCastWithTransform<N, V, M> for Capsule<N> { }

impl<'self,
     N:  Ord + Num + Float + Cast<f32> + Clone,
     V:  AlgebraicVecExt<N> + Clone,
     G1: Implicit<N, V, M>,
     G2: Implicit<N, V, M>,
     M>
RayCast<N, V> for MinkowskiSum<'self, M, G1, G2> {
    fn toi_and_normal_with_ray(&self, ray: &Ray<V>) -> Option<(N, V)> {
        gjk_toi_and_normal_with_ray(&Identity::new(), self, &mut JohnsonSimplex::<N, V>::new_w_tls(), ray)
    }
}

impl<'self,
     N:  Ord + Num + Float + Cast<f32> + Clone,
     V:  AlgebraicVecExt<N> + Clone,
     G1: Implicit<N, V, M>,
     G2: Implicit<N, V, M>,
     M:  Rotate<V> + Transform<V>>
RayCastWithTransform<N, V, M> for MinkowskiSum<'self, M, G1, G2> { }
<|endoftext|>


<commit_before>// id                   number              A unique identifier for each
// Droplet instance. This is automatically generated upon Droplet creation.
// name                 string              The human-readable name set for the
// Droplet instance.
// memory               number              Memory of the Droplet in megabytes.
// vcpus                number              The number of virtual CPUs.
// disk                 number              The size of the Droplet's disk in
// gigabytes.
// locked               boolean             A boolean value indicating whether
// the Droplet has been locked, preventing actions by users.
// created_at           string              A time value given in ISO8601
// combined date and time format that represents when the Droplet was created.
// status               string              A status string indicating the
// state of the Droplet instance. This may be "new", "active", "off", or
// "archive".
// backup_ids           array               An array of backup IDs of any
// backups that have been taken of the Droplet instance. Droplet backups are
// enabled at the time of the instance creation.
// snapshot_ids         array               An array of snapshot IDs of any
// snapshots created from the Droplet instance.
// features             array               An array of features enabled on
// this Droplet.
// region               object              The region that the Droplet
// instance is deployed in. When setting a region, the value should be the slug
// identifier for the region. When you query a Droplet, the entire region
// object will be returned.
// image                object              The base image used to create the
// Droplet instance. When setting an image, the value is set to the image id or
// slug. When querying the Droplet, the entire image object will be returned.
// size                 object              The current size object describing
// the Droplet. When setting a size, the value is set to the size slug. When
// querying the Droplet, the entire size object will be returned. Note that the
// disk volume of a droplet may not match the size's disk due to Droplet resize
// actions. The disk attribute on the Droplet should always be referenced.
// size_slug            string              The unique slug identifier for the
// size of this Droplet.
// networks             object              The details of the network that are
// configured for the Droplet instance. This is an object that contains keys
// for IPv4 and IPv6. The value of each of these is an array that contains
// objects describing an individual IP resource allocated to the Droplet. These
// will define attributes like the IP address, netmask, and gateway of the
// specific network depending on the type of network it is.
// kernel               nullable object     The current kernel. This will
// initially be set to the kernel of the base image when the Droplet is created.
// next_backup_window   nullable object     The details of the Droplet's
// backups feature, if backups are configured for the Droplet. This object
// contains keys for the start and end times of the window during which the
// backup will start.

use std::fmt;
use std::borrow::Cow;

use response::{self, Backup, Image, Kernel, NamedResponse, Networks, Region, Size};

#[derive(Deserialize, Debug)]
pub struct Droplet {
    id: f64,
    name: String,
    memory: f64,
    vcpus: f64,
    disk: f64,
    locked: bool,
    status: String,
    kernel: Option<Kernel>,
    created_at: String,
    features: Vec<String>,
    backup_ids: Vec<Option<String>>,
    next_backup_window: Option<Backup>,
    snapshot_ids: Vec<Option<String>>,
    image: Image,
    region: Region,
    size: Size,
    size_slug: String,
    networks: Networks,
}

impl response::NotArray for Droplet {}

impl fmt::Display for Droplet {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "ID: {:.0}\n\
                  Name: {}\n\
                  Memory: {} MB\n\
                  Virtual CPUs: {:.0}\n\
                  Disk: {} GB\n\
                  Locked: {}\n\
                  Created At: {}\n\
                  Status: {}\n\
                  Backup IDs: {}\n\
                  Snapshot IDs: {}\n\
                  Features: {}\n\
                  Region: \n\t{}\n\
                  Image: \n\t{}\n\
                  Size: \n\t{}\n\
                  Size Slug: {}\n\
                  Network: \n\t{}\n\
                  Kernel: \n\t{}\n\
                  Next Backup Window: {}\n",
               self.id,
               self.name,
               self.memory,
               self.vcpus,
               self.disk,
               self.locked,
               self.created_at,
               self.status,
               self.backup_ids
                   .iter()
                   .filter_map(|n| {
                       if n.is_some() {
                           Some(n.clone().unwrap().to_string())
                       } else {
                           None
                       }
                   })
                   .fold(String::new(), |acc, s| acc + &format!(" {},", s)[..]),
               self.snapshot_ids
                   .iter()
                   .filter_map(|n| {
                       if n.is_some() {
                           Some(n.clone().unwrap().to_string())
                       } else {
                           None
                       }
                   })
                   .fold(String::new(), |acc, s| acc + &format!(" {},", s)[..]),
               self.features
                   .iter()
                   .fold(String::new(), |acc, s| acc + &format!(" {},", s)[..]),
               &self.region.to_string()[..].replace("\n", "\n\t"),
               &self.image.to_string()[..].replace("\n", "\n\t"),
               &self.size.to_string()[..].replace("\n", "\n\t"),
               self.size_slug,
               &self.networks.to_string()[..].replace("\n", "\n\t"),
               if let Some(ref k) = self.kernel {
                   format!("{}", &k.to_string()[..].replace("\n", "\n\t"))
               } else {
                   "None".to_owned()
               },
               if let Some(ref k) = self.next_backup_window {
                   format!("{}", &k.to_string()[..].replace("\n", "\n\t"))
               } else {
                   "None".to_owned()
               })

    }
}

impl NamedResponse for Droplet {
    fn name<'a>() -> Cow<'a, str> {
        "droplet".into()
    }
}

pub type Droplets = Vec<Droplet>;
<commit_msg>fix: make response::Droplet's fields public<commit_after>// id                   number              A unique identifier for each
// Droplet instance. This is automatically generated upon Droplet creation.
// name                 string              The human-readable name set for the
// Droplet instance.
// memory               number              Memory of the Droplet in megabytes.
// vcpus                number              The number of virtual CPUs.
// disk                 number              The size of the Droplet's disk in
// gigabytes.
// locked               boolean             A boolean value indicating whether
// the Droplet has been locked, preventing actions by users.
// created_at           string              A time value given in ISO8601
// combined date and time format that represents when the Droplet was created.
// status               string              A status string indicating the
// state of the Droplet instance. This may be "new", "active", "off", or
// "archive".
// backup_ids           array               An array of backup IDs of any
// backups that have been taken of the Droplet instance. Droplet backups are
// enabled at the time of the instance creation.
// snapshot_ids         array               An array of snapshot IDs of any
// snapshots created from the Droplet instance.
// features             array               An array of features enabled on
// this Droplet.
// region               object              The region that the Droplet
// instance is deployed in. When setting a region, the value should be the slug
// identifier for the region. When you query a Droplet, the entire region
// object will be returned.
// image                object              The base image used to create the
// Droplet instance. When setting an image, the value is set to the image id or
// slug. When querying the Droplet, the entire image object will be returned.
// size                 object              The current size object describing
// the Droplet. When setting a size, the value is set to the size slug. When
// querying the Droplet, the entire size object will be returned. Note that the
// disk volume of a droplet may not match the size's disk due to Droplet resize
// actions. The disk attribute on the Droplet should always be referenced.
// size_slug            string              The unique slug identifier for the
// size of this Droplet.
// networks             object              The details of the network that are
// configured for the Droplet instance. This is an object that contains keys
// for IPv4 and IPv6. The value of each of these is an array that contains
// objects describing an individual IP resource allocated to the Droplet. These
// will define attributes like the IP address, netmask, and gateway of the
// specific network depending on the type of network it is.
// kernel               nullable object     The current kernel. This will
// initially be set to the kernel of the base image when the Droplet is created.
// next_backup_window   nullable object     The details of the Droplet's
// backups feature, if backups are configured for the Droplet. This object
// contains keys for the start and end times of the window during which the
// backup will start.

use std::fmt;
use std::borrow::Cow;

use response::{self, Backup, Image, Kernel, NamedResponse, Networks, Region, Size};

#[derive(Deserialize, Debug)]
pub struct Droplet {
    pub id: f64,
    pub name: String,
    pub memory: f64,
    pub vcpus: f64,
    pub disk: f64,
    pub locked: bool,
    pub status: String,
    pub kernel: Option<Kernel>,
    pub created_at: String,
    pub features: Vec<String>,
    pub backup_ids: Vec<Option<String>>,
    pub next_backup_window: Option<Backup>,
    pub snapshot_ids: Vec<Option<String>>,
    pub image: Image,
    pub region: Region,
    pub size: Size,
    pub size_slug: String,
    pub networks: Networks,
}

impl response::NotArray for Droplet {}

impl fmt::Display for Droplet {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "ID: {:.0}\n\
                  Name: {}\n\
                  Memory: {} MB\n\
                  Virtual CPUs: {:.0}\n\
                  Disk: {} GB\n\
                  Locked: {}\n\
                  Created At: {}\n\
                  Status: {}\n\
                  Backup IDs: {}\n\
                  Snapshot IDs: {}\n\
                  Features: {}\n\
                  Region: \n\t{}\n\
                  Image: \n\t{}\n\
                  Size: \n\t{}\n\
                  Size Slug: {}\n\
                  Network: \n\t{}\n\
                  Kernel: \n\t{}\n\
                  Next Backup Window: {}\n",
               self.id,
               self.name,
               self.memory,
               self.vcpus,
               self.disk,
               self.locked,
               self.created_at,
               self.status,
               self.backup_ids
                   .iter()
                   .filter_map(|n| {
                       if n.is_some() {
                           Some(n.clone().unwrap().to_string())
                       } else {
                           None
                       }
                   })
                   .fold(String::new(), |acc, s| acc + &format!(" {},", s)[..]),
               self.snapshot_ids
                   .iter()
                   .filter_map(|n| {
                       if n.is_some() {
                           Some(n.clone().unwrap().to_string())
                       } else {
                           None
                       }
                   })
                   .fold(String::new(), |acc, s| acc + &format!(" {},", s)[..]),
               self.features
                   .iter()
                   .fold(String::new(), |acc, s| acc + &format!(" {},", s)[..]),
               &self.region.to_string()[..].replace("\n", "\n\t"),
               &self.image.to_string()[..].replace("\n", "\n\t"),
               &self.size.to_string()[..].replace("\n", "\n\t"),
               self.size_slug,
               &self.networks.to_string()[..].replace("\n", "\n\t"),
               if let Some(ref k) = self.kernel {
                   format!("{}", &k.to_string()[..].replace("\n", "\n\t"))
               } else {
                   "None".to_owned()
               },
               if let Some(ref k) = self.next_backup_window {
                   format!("{}", &k.to_string()[..].replace("\n", "\n\t"))
               } else {
                   "None".to_owned()
               })

    }
}

impl NamedResponse for Droplet {
    fn name<'a>() -> Cow<'a, str> {
        "droplet".into()
    }
}

pub type Droplets = Vec<Droplet>;
<|endoftext|>


<commit_before>// Copyright 2018 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

//! Provides a [`Transport`] trait as well as implementations.
//!
//! The rpc crate is transport- and protocol-agnostic. Any transport that impls [`Transport`]
//! can be plugged in, using whatever protocol it wants.

use futures::prelude::*;
use std::{io, net::SocketAddr};

pub mod channel;

/// A bidirectional stream ([`Sink`] + [`Stream`]) of messages.
pub trait Transport
where
    Self: Stream<Item = io::Result<<Self as Transport>::Item>>,
    Self: Sink<SinkItem = <Self as Transport>::SinkItem, SinkError = io::Error>,
{
    /// The type read off the transport.
    type Item;
    /// The type written to the transport.
    type SinkItem;

    /// The address of the remote peer this transport is in communication with.
    fn peer_addr(&self) -> io::Result<SocketAddr>;
    /// The address of the local half of this transport.
    fn local_addr(&self) -> io::Result<SocketAddr>;
}
<commit_msg>Helper fn to create transports<commit_after>// Copyright 2018 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

//! Provides a [`Transport`] trait as well as implementations.
//!
//! The rpc crate is transport- and protocol-agnostic. Any transport that impls [`Transport`]
//! can be plugged in, using whatever protocol it wants.

use futures::prelude::*;
use std::{io, net::SocketAddr, pin::Pin, task::{Poll, LocalWaker}};

pub mod channel;

/// A bidirectional stream ([`Sink`] + [`Stream`]) of messages.
pub trait Transport
where
    Self: Stream<Item = io::Result<<Self as Transport>::Item>>,
    Self: Sink<SinkItem = <Self as Transport>::SinkItem, SinkError = io::Error>,
{
    /// The type read off the transport.
    type Item;
    /// The type written to the transport.
    type SinkItem;

    /// The address of the remote peer this transport is in communication with.
    fn peer_addr(&self) -> io::Result<SocketAddr>;
    /// The address of the local half of this transport.
    fn local_addr(&self) -> io::Result<SocketAddr>;
}

/// Returns a new Transport backed by the given Stream + Sink and connecting addresses.
pub fn new<S, Item>(inner: S, peer_addr: SocketAddr, local_addr: SocketAddr) -> impl Transport<Item = Item, SinkItem = S::SinkItem>
where
    S: Stream<Item = io::Result<Item>>,
    S: Sink<SinkError = io::Error>,
{
    TransportShim { inner, peer_addr, local_addr }
}

/// A transport created by adding peers to a Stream + Sink.
#[derive(Debug)]
struct TransportShim<S> {
    peer_addr: SocketAddr,
    local_addr: SocketAddr,
    inner: S,
}

impl<S> TransportShim<S> {
    pin_utils::unsafe_pinned!(inner: S);

}

impl<S> Stream for TransportShim<S>
where
    S: Stream,
{
    type Item = S::Item;

    fn poll_next(mut self: Pin<&mut Self>, waker: &LocalWaker) -> Poll<Option<S::Item>> {
        self.inner().poll_next(waker)
    }
}

impl<S> Sink for TransportShim<S>
where
    S: Sink
{
    type SinkItem = S::SinkItem;
    type SinkError = S::SinkError;

    fn start_send(mut self: Pin<&mut Self>, item: S::SinkItem) -> Result<(), S::SinkError> {
        self.inner().start_send(item)
    }

    fn poll_ready(mut self: Pin<&mut Self>, waker: &LocalWaker) -> Poll<Result<(), S::SinkError>> {
        self.inner().poll_ready(waker)
    }

    fn poll_flush(mut self: Pin<&mut Self>, waker: &LocalWaker) -> Poll<Result<(), S::SinkError>> {
        self.inner().poll_flush(waker)
    }

    fn poll_close(mut self: Pin<&mut Self>, waker: &LocalWaker) -> Poll<Result<(), S::SinkError>> {
        self.inner().poll_close(waker)
    }
}

impl<S, Item> Transport for TransportShim<S>
where
    S: Stream + Sink,
    Self: Stream<Item = io::Result<Item>>,
    Self: Sink<SinkItem = S::SinkItem, SinkError = io::Error>,
{
    type Item = Item;
    type SinkItem = S::SinkItem;

    /// The address of the remote peer this transport is in communication with.
    fn peer_addr(&self) -> io::Result<SocketAddr> {
        Ok(self.peer_addr)
    }

    /// The address of the local half of this transport.
    fn local_addr(&self) -> io::Result<SocketAddr> {
        Ok(self.local_addr)
    }
}
<|endoftext|>