<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 frames = &capture.frames[capture.actual_start..];

        write!(fmt, "Backtrace ")?;

        let mut dbg = fmt.debug_list();

        for frame in frames {
            if frame.frame.ip().is_null() {
                continue;
            }

            dbg.entries(&frame.symbols);
        }

        dbg.finish()
    }
}

impl fmt::Debug for BacktraceSymbol {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(fmt, "{{ ")?;

        if let Some(fn_name) = self.name.as_ref().map(|b| backtrace::SymbolName::new(b)) {
            write!(fmt, "fn: \"{:#}\"", fn_name)?;
        } else {
            write!(fmt, "fn: <unknown>")?;
        }

        if let Some(fname) = self.filename.as_ref() {
            write!(fmt, ", file: {:?}", fname)?;
        }

        if let Some(line) = self.lineno.as_ref() {
            write!(fmt, ", line: {:?}", line)?;
        }

        write!(fmt, " }}")
    }
}

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::Short,
            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.is_empty() {
            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(),
                    });
                });
            }
        }
    }
}
<commit_msg>Add quotes around filename in Backtrace debug<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();

        let frames = &capture.frames[capture.actual_start..];

        write!(fmt, "Backtrace ")?;

        let mut dbg = fmt.debug_list();

        for frame in frames {
            if frame.frame.ip().is_null() {
                continue;
            }

            dbg.entries(&frame.symbols);
        }

        dbg.finish()
    }
}

impl fmt::Debug for BacktraceSymbol {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(fmt, "{{ ")?;

        if let Some(fn_name) = self.name.as_ref().map(|b| backtrace::SymbolName::new(b)) {
            write!(fmt, "fn: \"{:#}\"", fn_name)?;
        } else {
            write!(fmt, "fn: <unknown>")?;
        }

        if let Some(fname) = self.filename.as_ref() {
            write!(fmt, ", file: \"{:?}\"", fname)?;
        }

        if let Some(line) = self.lineno.as_ref() {
            write!(fmt, ", line: {:?}", line)?;
        }

        write!(fmt, " }}")
    }
}

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::Short,
            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.is_empty() {
            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(),
                    });
                });
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(feature = "std_misc")]

use convert::{Into, From};
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use error::Error;
use fmt;
use io;
use iter::Iterator;
use libc;
use mem;
use ops::Deref;
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
use slice;
use string::String;
use vec::Vec;

/// A type representing an owned C-compatible string
///
/// This type serves the primary purpose of being able to safely generate a
/// C-compatible string from a Rust byte slice or vector. An instance of this
/// type is a static guarantee that the underlying bytes contain no interior 0
/// bytes and the final byte is 0.
///
/// A `CString` is created from either a byte slice or a byte vector. After
/// being created, a `CString` predominately inherits all of its methods from
/// the `Deref` implementation to `[libc::c_char]`. Note that the underlying
/// array is represented as an array of `libc::c_char` as opposed to `u8`. A
/// `u8` slice can be obtained with the `as_bytes` method.  Slices produced from
/// a `CString` do *not* contain the trailing nul terminator unless otherwise
/// specified.
///
/// # Examples
///
/// ```no_run
/// # #![feature(libc)]
/// # extern crate libc;
/// # fn main() {
/// use std::ffi::CString;
/// use libc;
///
/// extern {
///     fn my_printer(s: *const libc::c_char);
/// }
///
/// let to_print = &b"Hello, world!"[..];
/// let c_to_print = CString::new(to_print).unwrap();
/// unsafe {
///     my_printer(c_to_print.as_ptr());
/// }
/// # }
/// ```
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CString {
    inner: Vec<u8>,
}

/// Representation of a borrowed C string.
///
/// This dynamically sized type is only safely constructed via a borrowed
/// version of an instance of `CString`. This type can be constructed from a raw
/// C string as well and represents a C string borrowed from another location.
///
/// Note that this structure is **not** `repr(C)` and is not recommended to be
/// placed in the signatures of FFI functions. Instead safe wrappers of FFI
/// functions may leverage the unsafe `from_ptr` constructor to provide a safe
/// interface to other consumers.
///
/// # Examples
///
/// Inspecting a foreign C string
///
/// ```no_run
/// # #![feature(libc)]
/// extern crate libc;
/// use std::ffi::CStr;
///
/// extern { fn my_string() -> *const libc::c_char; }
///
/// fn main() {
///     unsafe {
///         let slice = CStr::from_ptr(my_string());
///         println!("string length: {}", slice.to_bytes().len());
///     }
/// }
/// ```
///
/// Passing a Rust-originating C string
///
/// ```no_run
/// # #![feature(libc)]
/// extern crate libc;
/// use std::ffi::{CString, CStr};
///
/// fn work(data: &CStr) {
///     extern { fn work_with(data: *const libc::c_char); }
///
///     unsafe { work_with(data.as_ptr()) }
/// }
///
/// fn main() {
///     let s = CString::new("data data data data").unwrap();
///     work(&s);
/// }
/// ```
#[derive(Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CStr {
    // FIXME: this should not be represented with a DST slice but rather with
    //        just a raw `libc::c_char` along with some form of marker to make
    //        this an unsized type. Essentially `sizeof(&CStr)` should be the
    //        same as `sizeof(&c_char)` but `CStr` should be an unsized type.
    inner: [libc::c_char]
}

/// An error returned from `CString::new` to indicate that a nul byte was found
/// in the vector provided.
#[derive(Clone, PartialEq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct NulError(usize, Vec<u8>);

impl CString {
    /// Create a new C-compatible string from a container of bytes.
    ///
    /// This method will consume the provided data and use the underlying bytes
    /// to construct a new string, ensuring that there is a trailing 0 byte.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # #![feature(libc)]
    /// extern crate libc;
    /// use std::ffi::CString;
    ///
    /// extern { fn puts(s: *const libc::c_char); }
    ///
    /// fn main() {
    ///     let to_print = CString::new("Hello!").unwrap();
    ///     unsafe {
    ///         puts(to_print.as_ptr());
    ///     }
    /// }
    /// ```
    ///
    /// # Errors
    ///
    /// This function will return an error if the bytes yielded contain an
    /// internal 0 byte. The error returned will contain the bytes as well as
    /// the position of the nul byte.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
        let bytes = t.into();
        match bytes.iter().position(|x| *x == 0) {
            Some(i) => Err(NulError(i, bytes)),
            None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
        }
    }

    /// Create a C-compatible string from a byte vector without checking for
    /// interior 0 bytes.
    ///
    /// This method is equivalent to `from_vec` except that no runtime assertion
    /// is made that `v` contains no 0 bytes.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
        v.push(0);
        CString { inner: v }
    }

    /// Returns the contents of this `CString` as a slice of bytes.
    ///
    /// The returned slice does **not** contain the trailing nul separator and
    /// it is guaranteed to not have any interior nul bytes.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_bytes(&self) -> &[u8] {
        &self.inner[..self.inner.len() - 1]
    }

    /// Equivalent to the `as_bytes` function except that the returned slice
    /// includes the trailing nul byte.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_bytes_with_nul(&self) -> &[u8] {
        &self.inner
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Deref for CString {
    type Target = CStr;

    fn deref(&self) -> &CStr {
        unsafe { mem::transmute(self.as_bytes_with_nul()) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for CString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&String::from_utf8_lossy(self.as_bytes()), f)
    }
}

impl NulError {
    /// Returns the position of the nul byte in the slice that was provided to
    /// `CString::from_vec`.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn nul_position(&self) -> usize { self.0 }

    /// Consumes this error, returning the underlying vector of bytes which
    /// generated the error in the first place.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_vec(self) -> Vec<u8> { self.1 }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Error for NulError {
    fn description(&self) -> &str { "nul byte found in data" }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for NulError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "nul byte found in provided data at position: {}", self.0)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl From<NulError> for io::Error {
    fn from(_: NulError) -> io::Error {
        io::Error::new(io::ErrorKind::InvalidInput,
                       "data provided contains a nul byte")
    }
}

impl CStr {
    /// Cast a raw C string to a safe C string wrapper.
    ///
    /// This function will cast the provided `ptr` to the `CStr` wrapper which
    /// allows inspection and interoperation of non-owned C strings. This method
    /// is unsafe for a number of reasons:
    ///
    /// * There is no guarantee to the validity of `ptr`
    /// * The returned lifetime is not guaranteed to be the actual lifetime of
    ///   `ptr`
    /// * There is no guarantee that the memory pointed to by `ptr` contains a
    ///   valid nul terminator byte at the end of the string.
    ///
    /// > **Note**: This operation is intended to be a 0-cost cast but it is
    /// > currently implemented with an up-front calculation of the length of
    /// > the string. This is not guaranteed to always be the case.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # #![feature(libc)]
    /// # extern crate libc;
    /// # fn main() {
    /// use std::ffi::CStr;
    /// use std::str;
    /// use libc;
    ///
    /// extern {
    ///     fn my_string() -> *const libc::c_char;
    /// }
    ///
    /// unsafe {
    ///     let slice = CStr::from_ptr(my_string());
    ///     println!("string returned: {}",
    ///              str::from_utf8(slice.to_bytes()).unwrap());
    /// }
    /// # }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr {
        let len = libc::strlen(ptr);
        mem::transmute(slice::from_raw_parts(ptr, len as usize + 1))
    }

    /// Return the inner pointer to this C string.
    ///
    /// The returned pointer will be valid for as long as `self` is and points
    /// to a contiguous region of memory terminated with a 0 byte to represent
    /// the end of the string.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_ptr(&self) -> *const libc::c_char {
        self.inner.as_ptr()
    }

    /// Convert this C string to a byte slice.
    ///
    /// This function will calculate the length of this string (which normally
    /// requires a linear amount of work to be done) and then return the
    /// resulting slice of `u8` elements.
    ///
    /// The returned slice will **not** contain the trailing nul that this C
    /// string has.
    ///
    /// > **Note**: This method is currently implemented as a 0-cost cast, but
    /// > it is planned to alter its definition in the future to perform the
    /// > length calculation whenever this method is called.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_bytes(&self) -> &[u8] {
        let bytes = self.to_bytes_with_nul();
        &bytes[..bytes.len() - 1]
    }

    /// Convert this C string to a byte slice containing the trailing 0 byte.
    ///
    /// This function is the equivalent of `to_bytes` except that it will retain
    /// the trailing nul instead of chopping it off.
    ///
    /// > **Note**: This method is currently implemented as a 0-cost cast, but
    /// > it is planned to alter its definition in the future to perform the
    /// > length calculation whenever this method is called.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_bytes_with_nul(&self) -> &[u8] {
        unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.inner) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for CStr {
    fn eq(&self, other: &CStr) -> bool {
        self.to_bytes().eq(other.to_bytes())
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for CStr {}
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd for CStr {
    fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
        self.to_bytes().partial_cmp(&other.to_bytes())
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for CStr {
    fn cmp(&self, other: &CStr) -> Ordering {
        self.to_bytes().cmp(&other.to_bytes())
    }
}

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

    #[test]
    fn c_to_rust() {
        let data = b"123\0";
        let ptr = data.as_ptr() as *const libc::c_char;
        unsafe {
            assert_eq!(CStr::from_ptr(ptr).to_bytes(), b"123");
            assert_eq!(CStr::from_ptr(ptr).to_bytes_with_nul(), b"123\0");
        }
    }

    #[test]
    fn simple() {
        let s = CString::new("1234").unwrap();
        assert_eq!(s.as_bytes(), b"1234");
        assert_eq!(s.as_bytes_with_nul(), b"1234\0");
    }

    #[test]
    fn build_with_zero1() {
        assert!(CString::new(&b"\0"[..]).is_err());
    }
    #[test]
    fn build_with_zero2() {
        assert!(CString::new(vec![0]).is_err());
    }

    #[test]
    fn build_with_zero3() {
        unsafe {
            let s = CString::from_vec_unchecked(vec![0]);
            assert_eq!(s.as_bytes(), b"\0");
        }
    }

    #[test]
    fn formatted() {
        let s = CString::new(&b"12"[..]).unwrap();
        assert_eq!(format!("{:?}", s), "\"12\"");
    }

    #[test]
    fn borrowed() {
        unsafe {
            let s = CStr::from_ptr(b"12\0".as_ptr() as *const _);
            assert_eq!(s.to_bytes(), b"12");
            assert_eq!(s.to_bytes_with_nul(), b"12\0");
        }
    }
}
<commit_msg>rollup merge of #24350: tbelaire/cstring-doc-from-vec<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(feature = "std_misc")]

use convert::{Into, From};
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use error::Error;
use fmt;
use io;
use iter::Iterator;
use libc;
use mem;
use ops::Deref;
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
use slice;
use string::String;
use vec::Vec;

/// A type representing an owned C-compatible string
///
/// This type serves the primary purpose of being able to safely generate a
/// C-compatible string from a Rust byte slice or vector. An instance of this
/// type is a static guarantee that the underlying bytes contain no interior 0
/// bytes and the final byte is 0.
///
/// A `CString` is created from either a byte slice or a byte vector. After
/// being created, a `CString` predominately inherits all of its methods from
/// the `Deref` implementation to `[libc::c_char]`. Note that the underlying
/// array is represented as an array of `libc::c_char` as opposed to `u8`. A
/// `u8` slice can be obtained with the `as_bytes` method.  Slices produced from
/// a `CString` do *not* contain the trailing nul terminator unless otherwise
/// specified.
///
/// # Examples
///
/// ```no_run
/// # #![feature(libc)]
/// # extern crate libc;
/// # fn main() {
/// use std::ffi::CString;
/// use libc;
///
/// extern {
///     fn my_printer(s: *const libc::c_char);
/// }
///
/// let to_print = &b"Hello, world!"[..];
/// let c_to_print = CString::new(to_print).unwrap();
/// unsafe {
///     my_printer(c_to_print.as_ptr());
/// }
/// # }
/// ```
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CString {
    inner: Vec<u8>,
}

/// Representation of a borrowed C string.
///
/// This dynamically sized type is only safely constructed via a borrowed
/// version of an instance of `CString`. This type can be constructed from a raw
/// C string as well and represents a C string borrowed from another location.
///
/// Note that this structure is **not** `repr(C)` and is not recommended to be
/// placed in the signatures of FFI functions. Instead safe wrappers of FFI
/// functions may leverage the unsafe `from_ptr` constructor to provide a safe
/// interface to other consumers.
///
/// # Examples
///
/// Inspecting a foreign C string
///
/// ```no_run
/// # #![feature(libc)]
/// extern crate libc;
/// use std::ffi::CStr;
///
/// extern { fn my_string() -> *const libc::c_char; }
///
/// fn main() {
///     unsafe {
///         let slice = CStr::from_ptr(my_string());
///         println!("string length: {}", slice.to_bytes().len());
///     }
/// }
/// ```
///
/// Passing a Rust-originating C string
///
/// ```no_run
/// # #![feature(libc)]
/// extern crate libc;
/// use std::ffi::{CString, CStr};
///
/// fn work(data: &CStr) {
///     extern { fn work_with(data: *const libc::c_char); }
///
///     unsafe { work_with(data.as_ptr()) }
/// }
///
/// fn main() {
///     let s = CString::new("data data data data").unwrap();
///     work(&s);
/// }
/// ```
#[derive(Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CStr {
    // FIXME: this should not be represented with a DST slice but rather with
    //        just a raw `libc::c_char` along with some form of marker to make
    //        this an unsized type. Essentially `sizeof(&CStr)` should be the
    //        same as `sizeof(&c_char)` but `CStr` should be an unsized type.
    inner: [libc::c_char]
}

/// An error returned from `CString::new` to indicate that a nul byte was found
/// in the vector provided.
#[derive(Clone, PartialEq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct NulError(usize, Vec<u8>);

impl CString {
    /// Create a new C-compatible string from a container of bytes.
    ///
    /// This method will consume the provided data and use the underlying bytes
    /// to construct a new string, ensuring that there is a trailing 0 byte.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # #![feature(libc)]
    /// extern crate libc;
    /// use std::ffi::CString;
    ///
    /// extern { fn puts(s: *const libc::c_char); }
    ///
    /// fn main() {
    ///     let to_print = CString::new("Hello!").unwrap();
    ///     unsafe {
    ///         puts(to_print.as_ptr());
    ///     }
    /// }
    /// ```
    ///
    /// # Errors
    ///
    /// This function will return an error if the bytes yielded contain an
    /// internal 0 byte. The error returned will contain the bytes as well as
    /// the position of the nul byte.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
        let bytes = t.into();
        match bytes.iter().position(|x| *x == 0) {
            Some(i) => Err(NulError(i, bytes)),
            None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
        }
    }

    /// Create a C-compatible string from a byte vector without checking for
    /// interior 0 bytes.
    ///
    /// This method is equivalent to `new` except that no runtime assertion
    /// is made that `v` contains no 0 bytes, and it requires an actual
    /// byte vector, not anyhting that can be converted to one with Into.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
        v.push(0);
        CString { inner: v }
    }

    /// Returns the contents of this `CString` as a slice of bytes.
    ///
    /// The returned slice does **not** contain the trailing nul separator and
    /// it is guaranteed to not have any interior nul bytes.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_bytes(&self) -> &[u8] {
        &self.inner[..self.inner.len() - 1]
    }

    /// Equivalent to the `as_bytes` function except that the returned slice
    /// includes the trailing nul byte.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_bytes_with_nul(&self) -> &[u8] {
        &self.inner
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Deref for CString {
    type Target = CStr;

    fn deref(&self) -> &CStr {
        unsafe { mem::transmute(self.as_bytes_with_nul()) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for CString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&String::from_utf8_lossy(self.as_bytes()), f)
    }
}

impl NulError {
    /// Returns the position of the nul byte in the slice that was provided to
    /// `CString::new`.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn nul_position(&self) -> usize { self.0 }

    /// Consumes this error, returning the underlying vector of bytes which
    /// generated the error in the first place.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_vec(self) -> Vec<u8> { self.1 }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Error for NulError {
    fn description(&self) -> &str { "nul byte found in data" }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for NulError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "nul byte found in provided data at position: {}", self.0)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl From<NulError> for io::Error {
    fn from(_: NulError) -> io::Error {
        io::Error::new(io::ErrorKind::InvalidInput,
                       "data provided contains a nul byte")
    }
}

impl CStr {
    /// Cast a raw C string to a safe C string wrapper.
    ///
    /// This function will cast the provided `ptr` to the `CStr` wrapper which
    /// allows inspection and interoperation of non-owned C strings. This method
    /// is unsafe for a number of reasons:
    ///
    /// * There is no guarantee to the validity of `ptr`
    /// * The returned lifetime is not guaranteed to be the actual lifetime of
    ///   `ptr`
    /// * There is no guarantee that the memory pointed to by `ptr` contains a
    ///   valid nul terminator byte at the end of the string.
    ///
    /// > **Note**: This operation is intended to be a 0-cost cast but it is
    /// > currently implemented with an up-front calculation of the length of
    /// > the string. This is not guaranteed to always be the case.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # #![feature(libc)]
    /// # extern crate libc;
    /// # fn main() {
    /// use std::ffi::CStr;
    /// use std::str;
    /// use libc;
    ///
    /// extern {
    ///     fn my_string() -> *const libc::c_char;
    /// }
    ///
    /// unsafe {
    ///     let slice = CStr::from_ptr(my_string());
    ///     println!("string returned: {}",
    ///              str::from_utf8(slice.to_bytes()).unwrap());
    /// }
    /// # }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr {
        let len = libc::strlen(ptr);
        mem::transmute(slice::from_raw_parts(ptr, len as usize + 1))
    }

    /// Return the inner pointer to this C string.
    ///
    /// The returned pointer will be valid for as long as `self` is and points
    /// to a contiguous region of memory terminated with a 0 byte to represent
    /// the end of the string.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_ptr(&self) -> *const libc::c_char {
        self.inner.as_ptr()
    }

    /// Convert this C string to a byte slice.
    ///
    /// This function will calculate the length of this string (which normally
    /// requires a linear amount of work to be done) and then return the
    /// resulting slice of `u8` elements.
    ///
    /// The returned slice will **not** contain the trailing nul that this C
    /// string has.
    ///
    /// > **Note**: This method is currently implemented as a 0-cost cast, but
    /// > it is planned to alter its definition in the future to perform the
    /// > length calculation whenever this method is called.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_bytes(&self) -> &[u8] {
        let bytes = self.to_bytes_with_nul();
        &bytes[..bytes.len() - 1]
    }

    /// Convert this C string to a byte slice containing the trailing 0 byte.
    ///
    /// This function is the equivalent of `to_bytes` except that it will retain
    /// the trailing nul instead of chopping it off.
    ///
    /// > **Note**: This method is currently implemented as a 0-cost cast, but
    /// > it is planned to alter its definition in the future to perform the
    /// > length calculation whenever this method is called.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_bytes_with_nul(&self) -> &[u8] {
        unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.inner) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for CStr {
    fn eq(&self, other: &CStr) -> bool {
        self.to_bytes().eq(other.to_bytes())
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for CStr {}
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd for CStr {
    fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
        self.to_bytes().partial_cmp(&other.to_bytes())
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for CStr {
    fn cmp(&self, other: &CStr) -> Ordering {
        self.to_bytes().cmp(&other.to_bytes())
    }
}

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

    #[test]
    fn c_to_rust() {
        let data = b"123\0";
        let ptr = data.as_ptr() as *const libc::c_char;
        unsafe {
            assert_eq!(CStr::from_ptr(ptr).to_bytes(), b"123");
            assert_eq!(CStr::from_ptr(ptr).to_bytes_with_nul(), b"123\0");
        }
    }

    #[test]
    fn simple() {
        let s = CString::new("1234").unwrap();
        assert_eq!(s.as_bytes(), b"1234");
        assert_eq!(s.as_bytes_with_nul(), b"1234\0");
    }

    #[test]
    fn build_with_zero1() {
        assert!(CString::new(&b"\0"[..]).is_err());
    }
    #[test]
    fn build_with_zero2() {
        assert!(CString::new(vec![0]).is_err());
    }

    #[test]
    fn build_with_zero3() {
        unsafe {
            let s = CString::from_vec_unchecked(vec![0]);
            assert_eq!(s.as_bytes(), b"\0");
        }
    }

    #[test]
    fn formatted() {
        let s = CString::new(&b"12"[..]).unwrap();
        assert_eq!(format!("{:?}", s), "\"12\"");
    }

    #[test]
    fn borrowed() {
        unsafe {
            let s = CStr::from_ptr(b"12\0".as_ptr() as *const _);
            assert_eq!(s.to_bytes(), b"12");
            assert_eq!(s.to_bytes_with_nul(), b"12\0");
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Unix System Programming Examples / Exemplier de programmation système Unix
 *
 * Copyright (C) 1995-2022 Alain Lebret <alain.lebret [at] ensicaen [dot] fr>
 *
 * 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.
 */

use nix::sys::ptrace;
use nix::sys::signal::Signal;
use nix::sys::wait::{WaitStatus, wait};
use nix::unistd::{fork, ForkResult, Pid};

use std::collections::HashMap;
use std::ffi::c_void;
use std::os::unix::process::CommandExt;
use std::process::{Command, exit};

extern crate linux_personality;
use linux_personality::personality;

fn set_breakpoint(pid: Pid, addr: u64) -> i64 {
    // Read 8 bytes from the process memory
    let value = ptrace::read(pid, addr as *mut c_void).unwrap();

    // Insert breakpoint by write new values
    let bp = (value & (i64::MAX ^ 0xFF)) | 0xCC;

    unsafe {
        ptrace::write(pid, addr as *mut c_void, bp as *mut c_void).unwrap();
    }

    // Return original bytecode
    value
}

fn restore_breakpoint(pid: Pid, addr: u64, orig_value: i64) {
    unsafe {
        // Restore original bytecode
        ptrace::write(pid, addr as *mut c_void, orig_value as *mut c_void).unwrap();
    }
}

fn handle_sigstop(pid: Pid, saved_values: &HashMap<u64, i64>) {
    let mut regs = ptrace::getregs(pid).unwrap();
    println!("Hit breakpoint at 0x{:x}", regs.rip - 1);

    match saved_values.get(&(regs.rip - 1)) {
        Some(orig) => {
            restore_breakpoint(pid, regs.rip - 1, *orig);

            // rewind rip
            regs.rip -= 1;
            ptrace::setregs(pid, regs).expect("Error rewinding RIP");

        }
        _ => print!("Nothing saved here"),
    }

    ptrace::cont(pid, None).expect("Restoring breakpoint failed");

}

// Code that runs only for child
fn manage_child() {
    // Allows process to be traced
    ptrace::traceme().unwrap();

    // Disable ASLR for this process
    personality(linux_personality::ADDR_NO_RANDOMIZE).unwrap();

    // Execute binary replacing
    Command::new("/home/carstein/sample").exec();

    exit(0);
}

// Code that runs only for parent
fn manage_parent(pid: Pid, breakpoints: &[u64]) {
    let mut saved_values = HashMap::new();

    // Placing breakpoints
    wait().unwrap();
    for addr in breakpoints.iter() {
        let orig = set_breakpoint(pid, *addr);
        saved_values.insert(*addr, orig);
    }
    ptrace::cont(pid, None).expect("Failed continue process");

    loop {
        match wait() {
            Ok(WaitStatus::Stopped(pid_t, sig_num)) => {
                match sig_num {
                    Signal::SIGTRAP => {
                        handle_sigstop(pid_t, &saved_values);
                    }

                    Signal::SIGSEGV => {
                        let regs = ptrace::getregs(pid_t).unwrap();
                        println!("Segmentation fault at 0x{:x}", regs.rip);
                        break
                    }
                    _ => {
                        println!("Some other signal - {}", sig_num);
                        break
                    }
                }
            },

            Ok(WaitStatus::Exited(pid, exit_status)) => {
                println!("Process with pid: {} exited with status {}", pid, exit_status);
                break;
            },

            Ok(status) =>  {
                println!("Received status: {:?}", status);
                ptrace::cont(pid, None).expect("Failed to deliver signal");
            },

            Err(err) => {
                println!("Some kind of error - {:?}",err);

            },
        }
    }
}

fn main() {
    // set breakpoints hash map
    let breakpoints: [u64; 1] = [0x8048451];

    match unsafe{fork()} {

        Ok(ForkResult::Child) => {
            manage_child();
        }

        Ok(ForkResult::Parent {child}) => {
            manage_parent(child, &breakpoints);
        }

        Err(err) => {
            panic!("[main] fork() failed: {}", err);
        }
    };
}<commit_msg>Delete process_03.rs<commit_after><|endoftext|>


<commit_before>use thread_comm::ThreadInfo;
use matrix::{Scalar,Mat,RoCM};
use core::ptr;
use core::marker::PhantomData;

pub struct PackPair<T: Scalar, At: Mat<T>, Apt: Mat<T>>
{
    pub a: At,
    pub ap: Apt,
    _t: PhantomData<T>,
}

impl<T: Scalar, At: Mat<T>, Apt: Mat<T>> PackPair<T, At, Apt> {
    pub fn new(a: At, ap: Apt) -> Self {
        PackPair{ a: a, ap: ap, _t: PhantomData }
    }
}

impl<T: Scalar, At: Mat<T>, Apt: Mat<T>> Mat<T> for PackPair<T, At, Apt> {
    #[inline(always)]
    fn get(&self, y: usize, x: usize) -> T { self.a.get(y,x) }
    #[inline(always)]
    fn set(&mut self, y: usize, x: usize, alpha: T) { self.a.set(y,x,alpha); }

    #[inline(always)]
    fn iter_height(&self) -> usize {
        self.a.iter_height()
    }
    #[inline(always)]
    fn iter_width(&self) -> usize {
        self.a.iter_width()
    }
    #[inline(always)]
    fn logical_h_padding(&self) -> usize {
        self.a.logical_h_padding()
    }
    #[inline(always)]
    fn logical_w_padding(&self) -> usize {
        self.a.logical_w_padding()
    }

    #[inline(always)]
    fn set_scalar(&mut self, alpha: T) {
        self.a.set_scalar(alpha);
        self.ap.set_scalar(alpha);
    }
    #[inline(always)]
    fn get_scalar(&self) -> T {
        self.a.get_scalar()
    }

    #[inline(always)]
    fn push_y_split(&mut self, start: usize, end: usize) {
        self.a.push_y_split(start, end);
        self.ap.push_y_split(start, end);
    }
    #[inline(always)]
    fn push_x_split(&mut self, start: usize, end: usize) {
        self.a.push_x_split(start, end);
        self.ap.push_x_split(start, end);
    }
    #[inline(always)]
    fn pop_y_split(&mut self) {
        self.a.pop_y_split();
        self.ap.pop_y_split();
    }
    #[inline(always)]
    fn pop_x_split(&mut self) {
        self.a.pop_x_split();
        self.ap.pop_x_split();
    }

    #[inline(always)]
    fn push_y_view(&mut self, blksz: usize) -> usize {
        self.a.push_y_view(blksz);
        self.ap.push_y_view(blksz)
    }

    #[inline(always)]
    fn push_x_view(&mut self, blksz: usize) -> usize {
        self.a.push_x_view(blksz);
        self.ap.push_x_view(blksz)
    }

    #[inline(always)]
    fn pop_y_view(&mut self) {
        self.a.pop_y_view();
        self.ap.pop_y_view();
    }

    #[inline(always)]
    fn pop_x_view(&mut self) {
        self.a.pop_x_view();
        self.ap.pop_x_view();
    }

    #[inline(always)]
    fn slide_y_view_to(&mut self, y: usize, blksz: usize) {
        self.a.slide_y_view_to(y, blksz);
        self.ap.slide_y_view_to(y, blksz);
    }

    #[inline(always)]
    fn slide_x_view_to(&mut self, x: usize, blksz: usize) {
        self.a.slide_x_view_to(x, blksz);
        self.ap.slide_x_view_to(x, blksz);
    }

    #[inline(always)]
    unsafe fn make_alias(&self) -> Self {
        let a_alias = self.a.make_alias();
        let ap_alias = self.ap.make_alias();
        PackPair{ a: a_alias, ap: ap_alias, _t: PhantomData }
    }

    #[inline(always)]
    unsafe fn send_alias(&mut self, thr: &ThreadInfo<T>) {
        self.a.send_alias(thr);
        self.ap.send_alias(thr);
    }
}
unsafe impl<T: Scalar, At: Mat<T>, Apt: Mat<T>> Send for PackPair<T, At, Apt> {}

impl<T: Scalar, At: Mat<T>, Apt: Mat<T>> RoCM<T> for PackPair<T, At, Apt>
    where At: RoCM<T>, Apt: RoCM<T>
{
    #[inline(always)]
    fn partition_is_rocm(&self) -> bool {
        self.a.partition_is_rocm() && self.ap.partition_is_rocm()
    }

    #[inline(always)]
    fn get_leaf_rs(&self) -> usize {
        self.ap.get_leaf_rs()
    }

    #[inline(always)]
    fn get_leaf_cs(&self) -> usize {
        self.ap.get_leaf_cs()
    }

    #[inline(always)]
    unsafe fn get_buffer(&self) -> *const T {
        self.ap.get_buffer()
    }

    #[inline(always)]
    unsafe fn establish_leaf(&mut self, y: usize, x: usize, height: usize, width: usize)
    {
        let a_buf = self.a.get_buffer().offset((y * self.a.get_block_rs(1,height)
            + x * self.a.get_block_cs(1,width)) as isize);
        let ap_buf = self.ap.get_mut_buffer().offset((y * self.ap.get_block_rs(1,height)
            + x * self.ap.get_block_cs(1,width)) as isize);

/*        if cfg!(feature="asm_snippets") && self.ap.get_leaf_cs() == 1 && self.a.get_leaf_cs() == 1 && width % 4 == 0 {
            for ii in 0..height {
                let a_ii = a_buf.offset((ii * self.a.get_leaf_rs()) as isize);
                let ap_ii = ap_buf.offset((ii * self.ap.get_leaf_rs()) as isize);

                for jj in (0..width).step_by(4) {
                    let a_ii_jj = a_ii.offset(jj as isize);
                    let ap_ii_jj = ap_ii.offset(jj as isize);

                    asm!("vmovupd ymm0, [$0]
                          vmovapd [$1], ymm0"
                        : : "r" (a_ii_jj),
                            "r"(ap_ii_jj)
                          : "ymm0 memory"
                          : "intel");
                    asm!("prefetcht0 ($0)" : : "r"(a_ii_jj.offset((4*self.a.get_leaf_rs()) as isize)));
                    asm!("prefetcht1 ($0)" : : "r"(ap_ii_jj.offset((8*self.a.get_leaf_rs()) as isize)));
                }
            }
        }
        else {*/
            for ii in 0..height {
                for jj in 0..width {
                    let alpha = ptr::read(a_buf.offset((ii * self.a.get_leaf_rs() + jj * self.a.get_leaf_cs()) as isize));
                    ptr::write(ap_buf.offset((ii * self.ap.get_leaf_rs() + jj * self.ap.get_leaf_cs()) as isize), alpha);
                }
            }
//        }
    }

    #[inline(always)]
    unsafe fn get_mut_buffer(&mut self) -> *mut T {
        self.ap.get_mut_buffer()
    }

    #[inline(always)]
    fn get_block_rs(&self, lvl: usize, blksz: usize) -> usize {
        self.ap.get_block_rs(lvl, blksz)
    }
    #[inline(always)]
    fn get_block_cs(&self, lvl: usize, blksz: usize) -> usize {
        self.ap.get_block_cs(lvl, blksz)
    }
    #[inline(always)]
    fn full_leaves() -> bool {
        Apt::full_leaves()
    }
}
<commit_msg>Tweak to overlapping packing<commit_after>use thread_comm::ThreadInfo;
use matrix::{Scalar,Mat,RoCM};
use core::ptr;
use core::marker::PhantomData;

pub struct PackPair<T: Scalar, At: Mat<T>, Apt: Mat<T>>
{
    pub a: At,
    pub ap: Apt,
    _t: PhantomData<T>,
}

impl<T: Scalar, At: Mat<T>, Apt: Mat<T>> PackPair<T, At, Apt> {
    pub fn new(a: At, ap: Apt) -> Self {
        PackPair{ a: a, ap: ap, _t: PhantomData }
    }
}

impl<T: Scalar, At: Mat<T>, Apt: Mat<T>> Mat<T> for PackPair<T, At, Apt> {
    #[inline(always)]
    fn get(&self, y: usize, x: usize) -> T { self.a.get(y,x) }
    #[inline(always)]
    fn set(&mut self, y: usize, x: usize, alpha: T) { self.a.set(y,x,alpha); }

    #[inline(always)]
    fn iter_height(&self) -> usize {
        self.a.iter_height()
    }
    #[inline(always)]
    fn iter_width(&self) -> usize {
        self.a.iter_width()
    }
    #[inline(always)]
    fn logical_h_padding(&self) -> usize {
        self.a.logical_h_padding()
    }
    #[inline(always)]
    fn logical_w_padding(&self) -> usize {
        self.a.logical_w_padding()
    }

    #[inline(always)]
    fn set_scalar(&mut self, alpha: T) {
        self.a.set_scalar(alpha);
        self.ap.set_scalar(alpha);
    }
    #[inline(always)]
    fn get_scalar(&self) -> T {
        self.a.get_scalar()
    }

    #[inline(always)]
    fn push_y_split(&mut self, start: usize, end: usize) {
        self.a.push_y_split(start, end);
        self.ap.push_y_split(start, end);
    }
    #[inline(always)]
    fn push_x_split(&mut self, start: usize, end: usize) {
        self.a.push_x_split(start, end);
        self.ap.push_x_split(start, end);
    }
    #[inline(always)]
    fn pop_y_split(&mut self) {
        self.a.pop_y_split();
        self.ap.pop_y_split();
    }
    #[inline(always)]
    fn pop_x_split(&mut self) {
        self.a.pop_x_split();
        self.ap.pop_x_split();
    }

    #[inline(always)]
    fn push_y_view(&mut self, blksz: usize) -> usize {
        self.a.push_y_view(blksz);
        self.ap.push_y_view(blksz)
    }

    #[inline(always)]
    fn push_x_view(&mut self, blksz: usize) -> usize {
        self.a.push_x_view(blksz);
        self.ap.push_x_view(blksz)
    }

    #[inline(always)]
    fn pop_y_view(&mut self) {
        self.a.pop_y_view();
        self.ap.pop_y_view();
    }

    #[inline(always)]
    fn pop_x_view(&mut self) {
        self.a.pop_x_view();
        self.ap.pop_x_view();
    }

    #[inline(always)]
    fn slide_y_view_to(&mut self, y: usize, blksz: usize) {
        self.a.slide_y_view_to(y, blksz);
        self.ap.slide_y_view_to(y, blksz);
    }

    #[inline(always)]
    fn slide_x_view_to(&mut self, x: usize, blksz: usize) {
        self.a.slide_x_view_to(x, blksz);
        self.ap.slide_x_view_to(x, blksz);
    }

    #[inline(always)]
    unsafe fn make_alias(&self) -> Self {
        let a_alias = self.a.make_alias();
        let ap_alias = self.ap.make_alias();
        PackPair{ a: a_alias, ap: ap_alias, _t: PhantomData }
    }

    #[inline(always)]
    unsafe fn send_alias(&mut self, thr: &ThreadInfo<T>) {
        self.a.send_alias(thr);
        self.ap.send_alias(thr);
    }
}
unsafe impl<T: Scalar, At: Mat<T>, Apt: Mat<T>> Send for PackPair<T, At, Apt> {}

impl<T: Scalar, At: Mat<T>, Apt: Mat<T>> RoCM<T> for PackPair<T, At, Apt>
    where At: RoCM<T>, Apt: RoCM<T>
{
    #[inline(always)]
    fn partition_is_rocm(&self) -> bool {
        self.a.partition_is_rocm() && self.ap.partition_is_rocm()
    }

    #[inline(always)]
    fn get_leaf_rs(&self) -> usize {
        self.ap.get_leaf_rs()
    }

    #[inline(always)]
    fn get_leaf_cs(&self) -> usize {
        self.ap.get_leaf_cs()
    }

    #[inline(always)]
    unsafe fn get_buffer(&self) -> *const T {
        self.ap.get_buffer()
    }

    #[inline(always)]
    unsafe fn establish_leaf(&mut self, y: usize, x: usize, height: usize, width: usize)
    {
        let a_buf = self.a.get_buffer().offset((y * self.a.get_block_rs(1,height)
            + x * self.a.get_block_cs(1,width)) as isize);
        let ap_buf = self.ap.get_mut_buffer().offset((y * self.ap.get_block_rs(1,height)
            + x * self.ap.get_block_cs(1,width)) as isize);

        if cfg!(feature="asm_snippets") && self.ap.get_leaf_cs() == 1 && self.a.get_leaf_cs() == 1 && width % 4 == 0 {
            for ii in 0..height {
                let a_ii = a_buf.offset((ii * self.a.get_leaf_rs()) as isize);
                let ap_ii = ap_buf.offset((ii * self.ap.get_leaf_rs()) as isize);

                for jj in (0..width).step_by(4) {
                    let a_ii_jj = a_ii.offset(jj as isize);
                    let ap_ii_jj = ap_ii.offset(jj as isize);

                    asm!("vmovupd ymm0, [$0]
                          vmovapd [$1], ymm0"
                        : : "r" (a_ii_jj),
                            "r"(ap_ii_jj)
                          : "ymm0 memory"
                          : "intel");
                    asm!("prefetcht0 ($0)" : : "r"(a_ii_jj.offset((4*self.a.get_leaf_rs()) as isize)));
                    //asm!("prefetchw ($0)" : : "r"(ap_ii_jj.offset((4*self.ap.get_leaf_rs()) as isize)));
                    //asm!("prefetcht2 ($0)" : : "r"(a_ii_jj.offset((16*self.a.get_leaf_rs()) as isize)));
                }
            }
        }
        else {
            for ii in 0..height {
                for jj in 0..width {
                    let alpha = ptr::read(a_buf.offset((ii * self.a.get_leaf_rs() + jj * self.a.get_leaf_cs()) as isize));
                    ptr::write(ap_buf.offset((ii * self.ap.get_leaf_rs() + jj * self.ap.get_leaf_cs()) as isize), alpha);
                }
            }
        }
    }

    #[inline(always)]
    unsafe fn get_mut_buffer(&mut self) -> *mut T {
        self.ap.get_mut_buffer()
    }

    #[inline(always)]
    fn get_block_rs(&self, lvl: usize, blksz: usize) -> usize {
        self.ap.get_block_rs(lvl, blksz)
    }
    #[inline(always)]
    fn get_block_cs(&self, lvl: usize, blksz: usize) -> usize {
        self.ap.get_block_cs(lvl, blksz)
    }
    #[inline(always)]
    fn full_leaves() -> bool {
        Apt::full_leaves()
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Dmitry "Divius" Tantsur <divius.inside@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//

//! KRPC DHT service as described in
//! [BEP 0005](http://www.bittorrent.org/beps/bep_0005.html).

use std::io::IoResult;
use std::sync;

use super::super::base;
use super::super::knodetable;

use super::udpwrapper;

/// Generic implementation of basic KRPC DHT on which BitTorrent DHT is based.
///
/// No peer retrival is supported: just finding and pinging nodes.
///
/// Usually you will be creating it as:
/// ```
/// let service = dht::bt::KRpcService::new_default(this_node);
/// ```
pub struct KRpcService<TNodeTable: base::GenericNodeTable,
                       TSocket: udpwrapper::GenericSocketWrapper> {
    this_node: base::Node,
    node_table: sync::Arc<sync::RWLock<TNodeTable>>,
    socket: TSocket,
    // this is for tests only, proper cancelling will follow later
    active: sync::Arc<sync::RWLock<bool>>,
}

/// Default kind of KRpc service.
pub type DefaultKRpcService = KRpcService<knodetable::KNodeTable, udpwrapper::UdpSocketWrapper>;

// This can't be derived, compiler is confused because of Arc.
impl<TNodeTable: base::GenericNodeTable,
     TSocket: udpwrapper::GenericSocketWrapper>
Clone for KRpcService<TNodeTable, TSocket> {
    fn clone(&self) -> KRpcService<TNodeTable, TSocket> {
        KRpcService {
            this_node: self.this_node.clone(),
            node_table: self.node_table.clone(),
            socket: self.socket.clone(),
            active: self.active.clone(),
        }
    }
}

fn handle_incoming<TNodeTable: base::GenericNodeTable,
                   TSocket: udpwrapper::GenericSocketWrapper>
                   (service: KRpcService<TNodeTable, TSocket>) {
    while *service.active.read() {}
    // TODO(divius): implement
}

impl KRpcService<knodetable::KNodeTable, udpwrapper::UdpSocketWrapper> {
    /// New service with default node table.
    pub fn new_default(this_node: base::Node) -> IoResult<DefaultKRpcService> {
        let node_table = knodetable::KNodeTable::new(this_node.id.clone());
        let socket = try!(udpwrapper::UdpSocketWrapper::new(&this_node));
        KRpcService::new(this_node, node_table, socket)
    }
}

impl<TNodeTable: base::GenericNodeTable,
     TSocket: udpwrapper::GenericSocketWrapper>
KRpcService<TNodeTable, TSocket> {
    /// New service with given node table and socket.
    pub fn new(this_node: base::Node, node_table: TNodeTable, socket: TSocket)
            -> IoResult<KRpcService<TNodeTable, TSocket>> {
        let self_ = KRpcService {
            this_node: this_node,
            node_table: sync::Arc::new(sync::RWLock::new(node_table)),
            socket: socket,
            active: sync::Arc::new(sync::RWLock::new(true)),
        };

        let self_clone = self_.clone();
        spawn(move || handle_incoming(self_clone));

        Ok(self_)
    }

    /// Get lock guarding access to a node table.
    pub fn node_table_lock(&self) -> &sync::RWLock<TNodeTable> {
        self.node_table.deref()
    }

    /// Get reference to a socket wrapper.
    ///
    /// Clone it if you want to get mutable copy.
    pub fn socket_ref(&self) -> &TSocket {
        &self.socket
    }
}

#[unsafe_destructor]
impl<TNodeTable: base::GenericNodeTable,
     TSocket: udpwrapper::GenericSocketWrapper>
Drop for KRpcService<TNodeTable, TSocket> {
    fn drop(&mut self) {
        *self.active.write() = false;
    }
}

#[cfg(test)]
mod test {
    use std::io::IoResult;
    use std::io::net::ip;

    use num;

    use super::super::super::base::{mod, GenericNodeTable};
    use super::super::super::utils::test;

    use super::super::protocol;
    use super::super::udpwrapper::GenericSocketWrapper;

    use super::KRpcService;

    struct DummyNodeTable {
        last_node: Option<base::Node>,
    }

    impl GenericNodeTable for DummyNodeTable {
        fn random_id(&self) -> num::BigUint {
            // This number is random, I promise :)
            test::uint_to_id(42)
        }

        fn update(&mut self, node: &base::Node) -> bool {
            self.last_node = Some(node.clone());
            true
        }
        #[allow(unused_variables)]
        fn find(&self, id: &num::BigUint, count: uint) -> Vec<base::Node> {
            match self.last_node {
                Some(ref n) if n.id == *id => vec![n.clone()],
                _ => vec![]
            }
        }
        fn pop_oldest(&mut self) -> Vec<base::Node> {
            vec![]
        }
    }

    #[deriving(Clone)]
    struct DummySocketWrapper {
        last_package: Option<protocol::Package>,
        last_node: Option<base::Node>
    }

    impl GenericSocketWrapper for DummySocketWrapper {
        fn send(&mut self, package: &protocol::Package, node: &base::Node)
            -> IoResult<()> {
            self.last_package = Some(package.clone());
            self.last_node = Some(node.clone());
            Ok(())
        }

        fn receive(&mut self) -> IoResult<(protocol::Package, ip::SocketAddr)> {
            Ok((self.last_package.as_ref().unwrap().clone(),
                self.last_node.as_ref().unwrap().address.clone()))
        }
    }

    #[test]
    fn test_new() {
        let n = test::new_node_with_port(42, 8007);
        let sock = DummySocketWrapper { last_package: None, last_node: None };
        let s = KRpcService::new(n.clone(),
                                 DummyNodeTable { last_node: None },
                                 sock).unwrap();
        assert_eq!(n.id, s.this_node.id);
        let mut nt = s.node_table_lock().write();
        nt.update(&test::new_node(1));
        assert_eq!(nt.random_id().to_u8().unwrap(), 42);
    }

    #[test]
    fn test_new_default() {
        let n = test::new_node_with_port(42, 8009);
        let s = KRpcService::new_default(n.clone()).unwrap();
        assert_eq!(n.id, s.this_node.id);
        let nt = s.node_table_lock().read();
        assert_eq!(0, nt.find(&test::uint_to_id(1), 1).len());
    }
}
<commit_msg>Use Thread::spawn instead of deprecated task::spawn<commit_after>// Copyright 2014 Dmitry "Divius" Tantsur <divius.inside@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//

//! KRPC DHT service as described in
//! [BEP 0005](http://www.bittorrent.org/beps/bep_0005.html).

use std::io::IoResult;
use std::sync;
use std::thread;

use super::super::base;
use super::super::knodetable;

use super::udpwrapper;

/// Generic implementation of basic KRPC DHT on which BitTorrent DHT is based.
///
/// No peer retrival is supported: just finding and pinging nodes.
///
/// Usually you will be creating it as:
/// ```
/// let service = dht::bt::KRpcService::new_default(this_node);
/// ```
pub struct KRpcService<TNodeTable: base::GenericNodeTable,
                       TSocket: udpwrapper::GenericSocketWrapper> {
    this_node: base::Node,
    node_table: sync::Arc<sync::RWLock<TNodeTable>>,
    socket: TSocket,
    // this is for tests only, proper cancelling will follow later
    active: sync::Arc<sync::RWLock<bool>>,
}

/// Default kind of KRpc service.
pub type DefaultKRpcService = KRpcService<knodetable::KNodeTable, udpwrapper::UdpSocketWrapper>;

// This can't be derived, compiler is confused because of Arc.
impl<TNodeTable: base::GenericNodeTable,
     TSocket: udpwrapper::GenericSocketWrapper>
Clone for KRpcService<TNodeTable, TSocket> {
    fn clone(&self) -> KRpcService<TNodeTable, TSocket> {
        KRpcService {
            this_node: self.this_node.clone(),
            node_table: self.node_table.clone(),
            socket: self.socket.clone(),
            active: self.active.clone(),
        }
    }
}

fn handle_incoming<TNodeTable: base::GenericNodeTable,
                   TSocket: udpwrapper::GenericSocketWrapper>
                   (service: KRpcService<TNodeTable, TSocket>) {
    while *service.active.read() {}
    // TODO(divius): implement
}

impl KRpcService<knodetable::KNodeTable, udpwrapper::UdpSocketWrapper> {
    /// New service with default node table.
    pub fn new_default(this_node: base::Node) -> IoResult<DefaultKRpcService> {
        let node_table = knodetable::KNodeTable::new(this_node.id.clone());
        let socket = try!(udpwrapper::UdpSocketWrapper::new(&this_node));
        KRpcService::new(this_node, node_table, socket)
    }
}

impl<TNodeTable: base::GenericNodeTable,
     TSocket: udpwrapper::GenericSocketWrapper>
KRpcService<TNodeTable, TSocket> {
    /// New service with given node table and socket.
    pub fn new(this_node: base::Node, node_table: TNodeTable, socket: TSocket)
            -> IoResult<KRpcService<TNodeTable, TSocket>> {
        let self_ = KRpcService {
            this_node: this_node,
            node_table: sync::Arc::new(sync::RWLock::new(node_table)),
            socket: socket,
            active: sync::Arc::new(sync::RWLock::new(true)),
        };

        let self_clone = self_.clone();
        thread::Thread::spawn(move || handle_incoming(self_clone)).detach();

        Ok(self_)
    }

    /// Get lock guarding access to a node table.
    pub fn node_table_lock(&self) -> &sync::RWLock<TNodeTable> {
        self.node_table.deref()
    }

    /// Get reference to a socket wrapper.
    ///
    /// Clone it if you want to get mutable copy.
    pub fn socket_ref(&self) -> &TSocket {
        &self.socket
    }
}

#[unsafe_destructor]
impl<TNodeTable: base::GenericNodeTable,
     TSocket: udpwrapper::GenericSocketWrapper>
Drop for KRpcService<TNodeTable, TSocket> {
    fn drop(&mut self) {
        *self.active.write() = false;
    }
}

#[cfg(test)]
mod test {
    use std::io::IoResult;
    use std::io::net::ip;

    use num;

    use super::super::super::base::{mod, GenericNodeTable};
    use super::super::super::utils::test;

    use super::super::protocol;
    use super::super::udpwrapper::GenericSocketWrapper;

    use super::KRpcService;

    struct DummyNodeTable {
        last_node: Option<base::Node>,
    }

    impl GenericNodeTable for DummyNodeTable {
        fn random_id(&self) -> num::BigUint {
            // This number is random, I promise :)
            test::uint_to_id(42)
        }

        fn update(&mut self, node: &base::Node) -> bool {
            self.last_node = Some(node.clone());
            true
        }
        #[allow(unused_variables)]
        fn find(&self, id: &num::BigUint, count: uint) -> Vec<base::Node> {
            match self.last_node {
                Some(ref n) if n.id == *id => vec![n.clone()],
                _ => vec![]
            }
        }
        fn pop_oldest(&mut self) -> Vec<base::Node> {
            vec![]
        }
    }

    #[deriving(Clone)]
    struct DummySocketWrapper {
        last_package: Option<protocol::Package>,
        last_node: Option<base::Node>
    }

    impl GenericSocketWrapper for DummySocketWrapper {
        fn send(&mut self, package: &protocol::Package, node: &base::Node)
            -> IoResult<()> {
            self.last_package = Some(package.clone());
            self.last_node = Some(node.clone());
            Ok(())
        }

        fn receive(&mut self) -> IoResult<(protocol::Package, ip::SocketAddr)> {
            Ok((self.last_package.as_ref().unwrap().clone(),
                self.last_node.as_ref().unwrap().address.clone()))
        }
    }

    #[test]
    fn test_new() {
        let n = test::new_node_with_port(42, 8007);
        let sock = DummySocketWrapper { last_package: None, last_node: None };
        let s = KRpcService::new(n.clone(),
                                 DummyNodeTable { last_node: None },
                                 sock).unwrap();
        assert_eq!(n.id, s.this_node.id);
        let mut nt = s.node_table_lock().write();
        nt.update(&test::new_node(1));
        assert_eq!(nt.random_id().to_u8().unwrap(), 42);
    }

    #[test]
    fn test_new_default() {
        let n = test::new_node_with_port(42, 8009);
        let s = KRpcService::new_default(n.clone()).unwrap();
        assert_eq!(n.id, s.this_node.id);
        let nt = s.node_table_lock().read();
        assert_eq!(0, nt.find(&test::uint_to_id(1), 1).len());
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2017, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

// TODO: support marshaller.

use std::mem;
use std::ptr;
use std::slice;

use libc::{c_uint, c_void};

use gobject_sys;
use translate::{from_glib_none, mut_override, ToGlibPtr, ToGlibPtrMut, Uninitialized};
use types::Type;
use ToValue;
use Value;

glib_wrapper! {
    #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
    pub struct Closure(Shared<gobject_sys::GClosure>);

    match fn {
        ref => |ptr| {
            gobject_sys::g_closure_ref(ptr);
            gobject_sys::g_closure_sink(ptr);
        },
        unref => |ptr| gobject_sys::g_closure_unref(ptr),
        get_type => || gobject_sys::g_closure_get_type(),
    }
}

impl Closure {
    pub fn new<F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static>(callback: F) -> Self {
        unsafe { Closure::new_unsafe(callback) }
    }

    pub fn new_local<F: Fn(&[Value]) -> Option<Value> + 'static>(callback: F) -> Self {
        let callback = crate::ThreadGuard::new(callback);

        unsafe { Closure::new_unsafe(move |values| (callback.get_ref())(values)) }
    }

    pub unsafe fn new_unsafe<F: Fn(&[Value]) -> Option<Value>>(callback: F) -> Self {
        unsafe extern "C" fn marshal<F>(
            _closure: *mut gobject_sys::GClosure,
            return_value: *mut gobject_sys::GValue,
            n_param_values: c_uint,
            param_values: *const gobject_sys::GValue,
            _invocation_hint: *mut c_void,
            marshal_data: *mut c_void,
        ) where
            F: Fn(&[Value]) -> Option<Value>,
        {
            let values = slice::from_raw_parts(param_values as *const _, n_param_values as usize);
            let callback: Box<F> = Box::from_raw(marshal_data as *mut _);
            let result = callback(values);
            if !return_value.is_null() {
                match result {
                    Some(result) => *return_value = result.into_raw(),
                    None => {
                        let result = Value::uninitialized();
                        *return_value = result.into_raw();
                    }
                }
            }
            mem::forget(callback);
        }

        unsafe extern "C" fn finalize<F>(
            notify_data: *mut c_void,
            _closure: *mut gobject_sys::GClosure,
        ) where
            F: Fn(&[Value]) -> Option<Value>,
        {
            let _callback: Box<F> = Box::from_raw(notify_data as *mut _);
            // callback is dropped here.
        }

        // Due to bitfields we have to do our own calculations here for the size of the GClosure:
        // - 4: 32 bits in guint bitfields at the beginning
        // - padding due to alignment needed for the following pointer
        // - 3 * size_of<*mut c_void>: 3 pointers
        // We don't store any custom data ourselves in the GClosure
        let size = u32::max(4, mem::align_of::<*mut c_void>() as u32)
            + 3 * mem::size_of::<*mut c_void>() as u32;
        let closure = gobject_sys::g_closure_new_simple(size, ptr::null_mut());
        assert_ne!(closure, ptr::null_mut());
        let callback = Box::new(callback);
        let ptr: *mut F = Box::into_raw(callback);
        let ptr: *mut c_void = ptr as *mut _;
        gobject_sys::g_closure_set_meta_marshal(closure, ptr, Some(marshal::<F>));
        gobject_sys::g_closure_add_finalize_notifier(closure, ptr, Some(finalize::<F>));
        from_glib_none(closure)
    }

    #[allow(clippy::redundant_closure)]
    pub fn invoke(&self, values: &[&dyn ToValue]) -> Option<Value> {
        let mut result = unsafe { Value::uninitialized() };

        let v_args: Vec<Value>;
        let mut s_args: [Value; 10] = unsafe { mem::zeroed() };
        let values = if values.len() <= 10 {
            for (i, arg) in values.iter().enumerate() {
                s_args[i] = arg.to_value();
            }
            &s_args[0..values.len()]
        } else {
            v_args = values.iter().map(|v| v.to_value()).collect();
            v_args.as_slice()
        };

        unsafe {
            gobject_sys::g_closure_invoke(
                self.to_glib_none().0 as *mut _,
                result.to_glib_none_mut().0,
                values.len() as u32,
                mut_override(values.as_ptr()) as *mut gobject_sys::GValue,
                ptr::null_mut(),
            );
        }
        if result.type_() == Type::Invalid {
            None
        } else {
            Some(result)
        }
    }
}

unsafe impl Send for Closure {}
unsafe impl Sync for Closure {}

#[cfg(test)]
mod tests {
    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::sync::Arc;

    use super::Closure;
    use ToValue;
    use Value;

    fn closure_fn(values: &[Value]) -> Option<Value> {
        assert_eq!(values.len(), 2);
        let string_arg = values[0].get::<String>();
        assert_eq!(string_arg, Ok(Some("test".to_string())));
        let int_arg = values[1].get_some::<i32>();
        assert_eq!(int_arg, Ok(42));
        Some(24.to_value())
    }

    #[test]
    fn test_closure() {
        let call_count = Arc::new(AtomicUsize::new(0));

        let count = call_count.clone();
        let closure = Closure::new(move |values| {
            count.fetch_add(1, Ordering::Relaxed);
            assert_eq!(values.len(), 2);
            let string_arg = values[0].get::<String>();
            assert_eq!(string_arg, Ok(Some("test".to_string())));
            let int_arg = values[1].get_some::<i32>();
            assert_eq!(int_arg, Ok(42));
            None
        });
        let result = closure.invoke(&[&"test".to_string(), &42]);
        assert!(result.is_none());
        assert_eq!(call_count.load(Ordering::Relaxed), 1);

        let result = closure.invoke(&[&"test".to_string(), &42]);
        assert!(result.is_none());
        assert_eq!(call_count.load(Ordering::Relaxed), 2);

        let closure = Closure::new(closure_fn);
        let result = closure.invoke(&[&"test".to_string(), &42]);
        let int_res = result.map(|result| result.get_some::<i32>());
        assert_eq!(int_res, Some(Ok(24)));
    }
}
<commit_msg>Remove unnecessary mem::forget() call in glib::Closure callback<commit_after>// Copyright 2013-2017, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

// TODO: support marshaller.

use std::mem;
use std::ptr;
use std::slice;

use libc::{c_uint, c_void};

use gobject_sys;
use translate::{from_glib_none, mut_override, ToGlibPtr, ToGlibPtrMut, Uninitialized};
use types::Type;
use ToValue;
use Value;

glib_wrapper! {
    #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
    pub struct Closure(Shared<gobject_sys::GClosure>);

    match fn {
        ref => |ptr| {
            gobject_sys::g_closure_ref(ptr);
            gobject_sys::g_closure_sink(ptr);
        },
        unref => |ptr| gobject_sys::g_closure_unref(ptr),
        get_type => || gobject_sys::g_closure_get_type(),
    }
}

impl Closure {
    pub fn new<F: Fn(&[Value]) -> Option<Value> + Send + Sync + 'static>(callback: F) -> Self {
        unsafe { Closure::new_unsafe(callback) }
    }

    pub fn new_local<F: Fn(&[Value]) -> Option<Value> + 'static>(callback: F) -> Self {
        let callback = crate::ThreadGuard::new(callback);

        unsafe { Closure::new_unsafe(move |values| (callback.get_ref())(values)) }
    }

    pub unsafe fn new_unsafe<F: Fn(&[Value]) -> Option<Value>>(callback: F) -> Self {
        unsafe extern "C" fn marshal<F>(
            _closure: *mut gobject_sys::GClosure,
            return_value: *mut gobject_sys::GValue,
            n_param_values: c_uint,
            param_values: *const gobject_sys::GValue,
            _invocation_hint: *mut c_void,
            marshal_data: *mut c_void,
        ) where
            F: Fn(&[Value]) -> Option<Value>,
        {
            let values = slice::from_raw_parts(param_values as *const _, n_param_values as usize);
            let callback: &F = &*(marshal_data as *mut _);
            let result = callback(values);
            if !return_value.is_null() {
                match result {
                    Some(result) => *return_value = result.into_raw(),
                    None => {
                        let result = Value::uninitialized();
                        *return_value = result.into_raw();
                    }
                }
            }
        }

        unsafe extern "C" fn finalize<F>(
            notify_data: *mut c_void,
            _closure: *mut gobject_sys::GClosure,
        ) where
            F: Fn(&[Value]) -> Option<Value>,
        {
            let _callback: Box<F> = Box::from_raw(notify_data as *mut _);
            // callback is dropped here.
        }

        // Due to bitfields we have to do our own calculations here for the size of the GClosure:
        // - 4: 32 bits in guint bitfields at the beginning
        // - padding due to alignment needed for the following pointer
        // - 3 * size_of<*mut c_void>: 3 pointers
        // We don't store any custom data ourselves in the GClosure
        let size = u32::max(4, mem::align_of::<*mut c_void>() as u32)
            + 3 * mem::size_of::<*mut c_void>() as u32;
        let closure = gobject_sys::g_closure_new_simple(size, ptr::null_mut());
        assert_ne!(closure, ptr::null_mut());
        let callback = Box::new(callback);
        let ptr: *mut F = Box::into_raw(callback);
        let ptr: *mut c_void = ptr as *mut _;
        gobject_sys::g_closure_set_meta_marshal(closure, ptr, Some(marshal::<F>));
        gobject_sys::g_closure_add_finalize_notifier(closure, ptr, Some(finalize::<F>));
        from_glib_none(closure)
    }

    #[allow(clippy::redundant_closure)]
    pub fn invoke(&self, values: &[&dyn ToValue]) -> Option<Value> {
        let mut result = unsafe { Value::uninitialized() };

        let v_args: Vec<Value>;
        let mut s_args: [Value; 10] = unsafe { mem::zeroed() };
        let values = if values.len() <= 10 {
            for (i, arg) in values.iter().enumerate() {
                s_args[i] = arg.to_value();
            }
            &s_args[0..values.len()]
        } else {
            v_args = values.iter().map(|v| v.to_value()).collect();
            v_args.as_slice()
        };

        unsafe {
            gobject_sys::g_closure_invoke(
                self.to_glib_none().0 as *mut _,
                result.to_glib_none_mut().0,
                values.len() as u32,
                mut_override(values.as_ptr()) as *mut gobject_sys::GValue,
                ptr::null_mut(),
            );
        }
        if result.type_() == Type::Invalid {
            None
        } else {
            Some(result)
        }
    }
}

unsafe impl Send for Closure {}
unsafe impl Sync for Closure {}

#[cfg(test)]
mod tests {
    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::sync::Arc;

    use super::Closure;
    use ToValue;
    use Value;

    fn closure_fn(values: &[Value]) -> Option<Value> {
        assert_eq!(values.len(), 2);
        let string_arg = values[0].get::<String>();
        assert_eq!(string_arg, Ok(Some("test".to_string())));
        let int_arg = values[1].get_some::<i32>();
        assert_eq!(int_arg, Ok(42));
        Some(24.to_value())
    }

    #[test]
    fn test_closure() {
        let call_count = Arc::new(AtomicUsize::new(0));

        let count = call_count.clone();
        let closure = Closure::new(move |values| {
            count.fetch_add(1, Ordering::Relaxed);
            assert_eq!(values.len(), 2);
            let string_arg = values[0].get::<String>();
            assert_eq!(string_arg, Ok(Some("test".to_string())));
            let int_arg = values[1].get_some::<i32>();
            assert_eq!(int_arg, Ok(42));
            None
        });
        let result = closure.invoke(&[&"test".to_string(), &42]);
        assert!(result.is_none());
        assert_eq!(call_count.load(Ordering::Relaxed), 1);

        let result = closure.invoke(&[&"test".to_string(), &42]);
        assert!(result.is_none());
        assert_eq!(call_count.load(Ordering::Relaxed), 2);

        let closure = Closure::new(closure_fn);
        let result = closure.invoke(&[&"test".to_string(), &42]);
        let int_res = result.map(|result| result.get_some::<i32>());
        assert_eq!(int_res, Some(Ok(24)));
    }
}
<|endoftext|>