<commit_before>//! Convenient utility methods, mostly for printing `syntect` data structures
//! prettily to the terminal.
use highlighting::{Style, StyleModifier};
use std::fmt::Write;
use std::ops::Range;
#[cfg(feature = "parsing")]
use parsing::ScopeStackOp;

/// Formats the styled fragments using 24-bit colour
/// terminal escape codes. Meant for debugging and testing.
/// It's currently fairly inefficient in its use of escape codes.
///
/// Note that this does not currently ever un-set the colour so that
/// the end of a line will also get highlighted with the background.
/// This means if you might want to use `println!("\x1b[0m");` after
/// to clear the colouring.
///
/// If `bg` is true then the background is also set
pub fn as_24_bit_terminal_escaped(v: &[(Style, &str)], bg: bool) -> String {
    let mut s: String = String::new();
    for &(ref style, text) in v.iter() {
        if bg {
            write!(s,
                   "\x1b[48;2;{};{};{}m",
                   style.background.r,
                   style.background.g,
                   style.background.b)
                .unwrap();
        }
        write!(s,
               "\x1b[38;2;{};{};{}m{}",
               style.foreground.r,
               style.foreground.g,
               style.foreground.b,
               text)
            .unwrap();
    }
    // s.push_str("\x1b[0m");
    s
}

/// Print out the various push and pop operations in a vector
/// with visual alignment to the line. Obviously for debugging.
#[cfg(feature = "parsing")]
pub fn debug_print_ops(line: &str, ops: &[(usize, ScopeStackOp)]) {
    for &(i, ref op) in ops.iter() {
        println!("{}", line.trim_right());
        print!("{: <1$}", "", i);
        match *op {
            ScopeStackOp::Push(s) => {
                println!("^ +{}", s);
            }
            ScopeStackOp::Pop(count) => {
                println!("^ pop {}", count);
            }
            ScopeStackOp::Clear(amount) => {
                println!("^ clear {:?}", amount);
            }
            ScopeStackOp::Restore => println!("^ restore"),
            ScopeStackOp::Noop => println!("noop"),
        }
    }
}

/// An iterator over the lines of a string, including the line endings.
///
/// This is similar to the standard library's `lines` method on `str`, except
/// that the yielded lines include the trailing newline character(s).
///
/// You can use it if you're parsing/highlighting some text that you have as a
/// string. With this, you can use the "newlines" variant of syntax definitions,
/// which is recommended.
///
/// # Examples
///
/// ```
/// use syntect::util::LinesWithEndings;
///
/// let mut lines = LinesWithEndings::from("foo\nbar\nbaz");
///
/// assert_eq!(Some("foo\n"), lines.next());
/// assert_eq!(Some("bar\n"), lines.next());
/// assert_eq!(Some("baz"), lines.next());
///
/// assert_eq!(None, lines.next());
/// ```
pub struct LinesWithEndings<'a> {
    input: &'a str,
}

impl<'a> LinesWithEndings<'a> {
    pub fn from(input: &'a str) -> LinesWithEndings<'a> {
        LinesWithEndings { input }
    }
}

impl<'a> Iterator for LinesWithEndings<'a> {
    type Item = &'a str;

    #[inline]
    fn next(&mut self) -> Option<&'a str> {
        if self.input.is_empty() {
            return None;
        }
        let split = self.input
            .find('\n')
            .map(|i| i + 1)
            .unwrap_or_else(|| self.input.len());
        let (line, rest) = self.input.split_at(split);
        self.input = rest;
        Some(line)
    }
}

/// Split a highlighted line at a byte index in the line into a before and
/// after component. It's just a helper that does the somewhat tricky logic
/// including splitting a span if the index lies on a boundary.
///
/// This can be used to extract a chunk of the line out for special treatment
/// like wrapping it in an HTML tag for extra styling.
///
/// Generic for testing purposes and fancier use cases, but intended for use with
/// the `Vec<(Style, &str)>` returned by `highlight` methods. Look at the source
/// code for `modify_range` for an example usage.
pub fn split_at<'a, A: Clone>(mut v: &[(A, &'a str)], mut split_i: usize) -> (Vec<(A, &'a str)>, Vec<(A, &'a str)>) {
  // Consume all tokens before the split
  let mut before = Vec::new();
  for tok in v {
    if tok.1.len() > split_i {
      break;
    }
    before.push(tok.clone());
    split_i -= tok.1.len();
  }
  v = &v[before.len()..];

  let mut after = Vec::new();
  // If necessary, split the token the split falls inside
  if v.len() > 0 && split_i > 0 {
    let (sa, sb) = v[0].1.split_at(split_i);
    before.push((v[0].0.clone(), sa));
    after.push((v[0].0.clone(), sb));
    v = &v[1..];
  }

  after.extend_from_slice(v);

  return (before, after);
}

/// Modify part of a highlighted line using a style modifier, useful for highlighting sections of a line.
///
/// # Examples
///
/// ```
/// use syntect::util::modify_range;
/// use syntect::highlighting::{Style, StyleModifier, FontStyle};
///
/// let plain = Style::default();
/// let boldmod = StyleModifier { foreground: None, background: None, font_style: Some(FontStyle::BOLD) };
/// let bold = plain.apply(boldmod);
///
/// let l = &[(plain, "abc"), (plain, "def"), (plain, "ghi")];
/// let l2 = modify_range(l, 1..6, boldmod);
/// assert_eq!(l2, &[(plain, "a"), (bold, "bc"), (bold, "def"), (plain, "ghi")]);
/// ```
pub fn modify_range<'a>(v: &[(Style, &'a str)], r: Range<usize>, modifier: StyleModifier) -> Vec<(Style, &'a str)> {
  let (mut result, in_and_after) = split_at(v, r.start);
  let (inside, mut after) = split_at(&in_and_after, r.end - r.start);

  result.extend(inside.iter().map(|(style, s)| { (style.apply(modifier), *s)}));
  result.append(&mut after);
  result
}

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

    #[test]
    fn test_lines_with_endings() {
        fn lines(s: &str) -> Vec<&str> {
            LinesWithEndings::from(s).collect()
        }

        assert!(lines("").is_empty());
        assert_eq!(lines("f"), vec!["f"]);
        assert_eq!(lines("foo"), vec!["foo"]);
        assert_eq!(lines("foo\n"), vec!["foo\n"]);
        assert_eq!(lines("foo\nbar"), vec!["foo\n", "bar"]);
        assert_eq!(lines("foo\nbar\n"), vec!["foo\n", "bar\n"]);
        assert_eq!(lines("foo\r\nbar"), vec!["foo\r\n", "bar"]);
        assert_eq!(lines("foo\r\nbar\r\n"), vec!["foo\r\n", "bar\r\n"]);
        assert_eq!(lines("\nfoo"), vec!["\n", "foo"]);
        assert_eq!(lines("\n\n\n"), vec!["\n", "\n", "\n"]);
    }

    #[test]
    fn test_split_at() {
      let l: &[(u8, &str)] = &[];
      let (before, after) = split_at(l, 0); // empty
      assert_eq!((&before[..], &after[..]), (&[][..],&[][..]));

      let l = &[(0u8, "abc"), (1u8, "def"), (2u8, "ghi")];

      let (before, after) = split_at(l, 0); // at start
      assert_eq!((&before[..], &after[..]), (&[][..],&[(0u8, "abc"), (1u8, "def"), (2u8, "ghi")][..]));

      let (before, after) = split_at(l, 4); // inside token
      assert_eq!((&before[..], &after[..]), (&[(0u8, "abc"), (1u8, "d")][..],&[(1u8, "ef"), (2u8, "ghi")][..]));

      let (before, after) = split_at(l, 3); // between tokens
      assert_eq!((&before[..], &after[..]), (&[(0u8, "abc")][..],&[(1u8, "def"), (2u8, "ghi")][..]));

      let (before, after) = split_at(l, 9); // just after last token
      assert_eq!((&before[..], &after[..]), (&[(0u8, "abc"), (1u8, "def"), (2u8, "ghi")][..], &[][..]));

      let (before, after) = split_at(l, 10); // out of bounds
      assert_eq!((&before[..], &after[..]), (&[(0u8, "abc"), (1u8, "def"), (2u8, "ghi")][..], &[][..]));
    }
}
<commit_msg>Fix indentation of new helpers<commit_after>//! Convenient utility methods, mostly for printing `syntect` data structures
//! prettily to the terminal.
use highlighting::{Style, StyleModifier};
use std::fmt::Write;
use std::ops::Range;
#[cfg(feature = "parsing")]
use parsing::ScopeStackOp;

/// Formats the styled fragments using 24-bit colour
/// terminal escape codes. Meant for debugging and testing.
/// It's currently fairly inefficient in its use of escape codes.
///
/// Note that this does not currently ever un-set the colour so that
/// the end of a line will also get highlighted with the background.
/// This means if you might want to use `println!("\x1b[0m");` after
/// to clear the colouring.
///
/// If `bg` is true then the background is also set
pub fn as_24_bit_terminal_escaped(v: &[(Style, &str)], bg: bool) -> String {
    let mut s: String = String::new();
    for &(ref style, text) in v.iter() {
        if bg {
            write!(s,
                   "\x1b[48;2;{};{};{}m",
                   style.background.r,
                   style.background.g,
                   style.background.b)
                .unwrap();
        }
        write!(s,
               "\x1b[38;2;{};{};{}m{}",
               style.foreground.r,
               style.foreground.g,
               style.foreground.b,
               text)
            .unwrap();
    }
    // s.push_str("\x1b[0m");
    s
}

/// Print out the various push and pop operations in a vector
/// with visual alignment to the line. Obviously for debugging.
#[cfg(feature = "parsing")]
pub fn debug_print_ops(line: &str, ops: &[(usize, ScopeStackOp)]) {
    for &(i, ref op) in ops.iter() {
        println!("{}", line.trim_right());
        print!("{: <1$}", "", i);
        match *op {
            ScopeStackOp::Push(s) => {
                println!("^ +{}", s);
            }
            ScopeStackOp::Pop(count) => {
                println!("^ pop {}", count);
            }
            ScopeStackOp::Clear(amount) => {
                println!("^ clear {:?}", amount);
            }
            ScopeStackOp::Restore => println!("^ restore"),
            ScopeStackOp::Noop => println!("noop"),
        }
    }
}

/// An iterator over the lines of a string, including the line endings.
///
/// This is similar to the standard library's `lines` method on `str`, except
/// that the yielded lines include the trailing newline character(s).
///
/// You can use it if you're parsing/highlighting some text that you have as a
/// string. With this, you can use the "newlines" variant of syntax definitions,
/// which is recommended.
///
/// # Examples
///
/// ```
/// use syntect::util::LinesWithEndings;
///
/// let mut lines = LinesWithEndings::from("foo\nbar\nbaz");
///
/// assert_eq!(Some("foo\n"), lines.next());
/// assert_eq!(Some("bar\n"), lines.next());
/// assert_eq!(Some("baz"), lines.next());
///
/// assert_eq!(None, lines.next());
/// ```
pub struct LinesWithEndings<'a> {
    input: &'a str,
}

impl<'a> LinesWithEndings<'a> {
    pub fn from(input: &'a str) -> LinesWithEndings<'a> {
        LinesWithEndings { input }
    }
}

impl<'a> Iterator for LinesWithEndings<'a> {
    type Item = &'a str;

    #[inline]
    fn next(&mut self) -> Option<&'a str> {
        if self.input.is_empty() {
            return None;
        }
        let split = self.input
            .find('\n')
            .map(|i| i + 1)
            .unwrap_or_else(|| self.input.len());
        let (line, rest) = self.input.split_at(split);
        self.input = rest;
        Some(line)
    }
}

/// Split a highlighted line at a byte index in the line into a before and
/// after component. It's just a helper that does the somewhat tricky logic
/// including splitting a span if the index lies on a boundary.
///
/// This can be used to extract a chunk of the line out for special treatment
/// like wrapping it in an HTML tag for extra styling.
///
/// Generic for testing purposes and fancier use cases, but intended for use with
/// the `Vec<(Style, &str)>` returned by `highlight` methods. Look at the source
/// code for `modify_range` for an example usage.
pub fn split_at<'a, A: Clone>(mut v: &[(A, &'a str)], mut split_i: usize) -> (Vec<(A, &'a str)>, Vec<(A, &'a str)>) {
    // Consume all tokens before the split
    let mut before = Vec::new();
    for tok in v {
        if tok.1.len() > split_i {
            break;
        }
        before.push(tok.clone());
        split_i -= tok.1.len();
    }
    v = &v[before.len()..];

    let mut after = Vec::new();
    // If necessary, split the token the split falls inside
    if v.len() > 0 && split_i > 0 {
        let (sa, sb) = v[0].1.split_at(split_i);
        before.push((v[0].0.clone(), sa));
        after.push((v[0].0.clone(), sb));
        v = &v[1..];
    }

    after.extend_from_slice(v);

    return (before, after);
}

/// Modify part of a highlighted line using a style modifier, useful for highlighting sections of a line.
///
/// # Examples
///
/// ```
/// use syntect::util::modify_range;
/// use syntect::highlighting::{Style, StyleModifier, FontStyle};
///
/// let plain = Style::default();
/// let boldmod = StyleModifier { foreground: None, background: None, font_style: Some(FontStyle::BOLD) };
/// let bold = plain.apply(boldmod);
///
/// let l = &[(plain, "abc"), (plain, "def"), (plain, "ghi")];
/// let l2 = modify_range(l, 1..6, boldmod);
/// assert_eq!(l2, &[(plain, "a"), (bold, "bc"), (bold, "def"), (plain, "ghi")]);
/// ```
pub fn modify_range<'a>(v: &[(Style, &'a str)], r: Range<usize>, modifier: StyleModifier) -> Vec<(Style, &'a str)> {
    let (mut result, in_and_after) = split_at(v, r.start);
    let (inside, mut after) = split_at(&in_and_after, r.end - r.start);

    result.extend(inside.iter().map(|(style, s)| { (style.apply(modifier), *s)}));
    result.append(&mut after);
    result
}

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

    #[test]
    fn test_lines_with_endings() {
        fn lines(s: &str) -> Vec<&str> {
            LinesWithEndings::from(s).collect()
        }

        assert!(lines("").is_empty());
        assert_eq!(lines("f"), vec!["f"]);
        assert_eq!(lines("foo"), vec!["foo"]);
        assert_eq!(lines("foo\n"), vec!["foo\n"]);
        assert_eq!(lines("foo\nbar"), vec!["foo\n", "bar"]);
        assert_eq!(lines("foo\nbar\n"), vec!["foo\n", "bar\n"]);
        assert_eq!(lines("foo\r\nbar"), vec!["foo\r\n", "bar"]);
        assert_eq!(lines("foo\r\nbar\r\n"), vec!["foo\r\n", "bar\r\n"]);
        assert_eq!(lines("\nfoo"), vec!["\n", "foo"]);
        assert_eq!(lines("\n\n\n"), vec!["\n", "\n", "\n"]);
    }

    #[test]
    fn test_split_at() {
        let l: &[(u8, &str)] = &[];
        let (before, after) = split_at(l, 0); // empty
        assert_eq!((&before[..], &after[..]), (&[][..],&[][..]));

        let l = &[(0u8, "abc"), (1u8, "def"), (2u8, "ghi")];

        let (before, after) = split_at(l, 0); // at start
        assert_eq!((&before[..], &after[..]), (&[][..],&[(0u8, "abc"), (1u8, "def"), (2u8, "ghi")][..]));

        let (before, after) = split_at(l, 4); // inside token
        assert_eq!((&before[..], &after[..]), (&[(0u8, "abc"), (1u8, "d")][..],&[(1u8, "ef"), (2u8, "ghi")][..]));

        let (before, after) = split_at(l, 3); // between tokens
        assert_eq!((&before[..], &after[..]), (&[(0u8, "abc")][..],&[(1u8, "def"), (2u8, "ghi")][..]));

        let (before, after) = split_at(l, 9); // just after last token
        assert_eq!((&before[..], &after[..]), (&[(0u8, "abc"), (1u8, "def"), (2u8, "ghi")][..], &[][..]));

        let (before, after) = split_at(l, 10); // out of bounds
        assert_eq!((&before[..], &after[..]), (&[(0u8, "abc"), (1u8, "def"), (2u8, "ghi")][..], &[][..]));
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.

//use std;
use std::{fmt, error};

pub mod ctl_op {
    /// Register the target file descriptor fd on the epoll instance
    /// referred to by the file descriptor epfd and associate the
    /// event with the internal file linked to fd.
    pub const ADD: u32 = 1;
    /// Change the event event associated with the target file descriptor fd.
    pub const MOD: u32 = 2;
    /// Remove (deregister) the target file descriptor fd from the epoll
    /// instance referred to by epfd. The event is ignored and can be NULL.
    pub const DEL: u32 = 3;
}

pub mod event_type {
    /// The associated file is available for read(2) operations.
    pub const EPOLLIN:          u32 = 0x001;
    /// The associated file is available for write(2) operations.
    pub const EPOLLOUT:         u32 = 0x004;
    /// Stream socket peer closed connection, or shut down writing
    /// half of connection.
    pub const EPOLLRDHUP:       u32 = 0x2000;
    /// There is urgent data available for read(2) operations.
    pub const EPOLLPRI:         u32 = 0x002;
    /// Error condition happened on the associated file descriptor.
    /// epoll_wait(2) will always wait for this event; it is not
    /// necessary to set it in events.
    pub const EPOLLERR:         u32 = 0x008;
    /// Hang up happened on the associated file descriptor. epoll_wait(2)
    /// will always wait for this event; it is not necessary to set it
    /// in events.
    pub const EPOLLHUP:         u32 = 0x010;
    /// Sets the Edge Triggered behavior for the associated file descriptor.
    /// The default behavior for epoll is Level Triggered.
    pub const EPOLLET:          u32 = (1 << 31);
    /// Sets the one-shot behavior for the associated file descriptor.
    /// This means that after an event is pulled out with epoll_wait(2)
    /// the associated file descriptor is internally disabled and no other
    /// events will be reported by the epoll interface. The user must call
    /// epoll_ctl() with EPOLL_CTL_MOD to rearm the file descriptor with a
    /// new event mask.
    pub const EPOLLONESHOT:     u32 = (1 << 30);
}

#[derive(Debug, Clone)]
pub enum CreateError {
    /// Invalid value specified in flags.
    EINVAL,
    /// The per-user limit on the number of epoll instances
    /// imposed by /proc/sys/fs/epoll/max_user_instances was encountered.
    EMFILE,
    /// The system limit on the total number of open files has been reached.
    ENFILE,
    /// There was insufficient memory to create the kernel object.
    ENOMEM
}

#[derive(Debug, Clone)]
pub enum CtlError {
    /// fd is not a valid file descriptor.
    EBADF,
    /// op was EPOLL_CTL_ADD, and the supplied file descriptor fd is already
    /// registered with this epoll instance.
    EEXIST,
    /// epfd is not an epoll file descriptor, or fd is the same as epfd,
    /// or the requested operation op is not supported by this interface.
    EINVAL,
    /// op was EPOLL_CTL_MOD or EPOLL_CTL_DEL, and fd is not registered
    /// with this epoll instance.
    ENOENT,
    /// There was insufficient memory to handle the requested op control
    /// operation.
    ENOSPC,
    /// The limit imposed by /proc/sys/fs/epoll/max_user_watches was
    /// encountered while trying to register (EPOLL_CTL_ADD) a new
    /// file descriptor on an epoll instance.
    EPERM
}

#[derive(Debug, Clone)]
pub enum WaitError {
    /// epfd is not a valid file descriptor.
    EBADF,
    /// The memory area pointed to by events is not accessible
    /// with write permissions.
    EFAULT,
    /// The call was interrupted by a signal handler before
    /// either any of the requested events occurred or the timeout expired.
    EINTR,
    /// epfd is not an epoll file descriptor, or maxevents is less than
    /// or equal to zero.
    EINVAL
}

impl error::Error for CreateError {
    fn description(&self) -> &str {
        match *self {
            CreateError::EINVAL => "Invalid flags",
            CreateError::EMFILE => "/proc/sys/fs/epoll/max_user_instances limit reached",
            CreateError::ENFILE => "NOFILE limit has been reached",
            CreateError::ENOMEM => "Insufficient memory"
        }
    }
}

impl error::Error for CtlError {
    fn description(&self) -> &str {
        match *self {
            CtlError::EBADF => "Invalid file descriptor",
            CtlError::EEXIST => "File descriptor already registered",
            CtlError::EINVAL => "epoll_fd is not an epoll file descriptor",
            CtlError::ENOENT => "File descriptor not registered",
            CtlError::ENOSPC => "Insufficient memory",
            CtlError::EPERM => "/proc/sys/fs/epoll/max_user_watches limit reached"
        }
    }
}

impl error::Error for WaitError {
    fn description(&self) -> &str {
        match *self {
            WaitError::EBADF => "Invalid file descriptor",
            WaitError::EFAULT => "Memory pointed to by events is not accessible with write permissions",
            WaitError::EINTR => "Interrupted by a signal before any requested events occurred or timeout expired",
            WaitError::EINVAL => "epoll_fd not an epoll file descriptor, or maxevents is less than or equal to zero."
        }
    }
}

impl fmt::Display for CreateError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            CreateError::EINVAL => "EINVAL".fmt(f),
            CreateError::EMFILE => "EMFILE".fmt(f),
            CreateError::ENFILE => "ENFILE".fmt(f),
            CreateError::ENOMEM => "ENOMEM".fmt(f)
        }
    }
}

impl fmt::Display for CtlError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            CtlError::EBADF => "EBADF".fmt(f),
            CtlError::EEXIST => "EEXIST".fmt(f),
            CtlError::EINVAL => "EINVAL".fmt(f),
            CtlError::ENOENT => "ENOENT".fmt(f),
            CtlError::ENOSPC => "ENOSPC".fmt(f),
            CtlError::EPERM => "EPERM".fmt(f)
        }
    }
}

impl fmt::Display for WaitError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            WaitError::EBADF => "EBADF".fmt(f),
            WaitError::EFAULT => "EFAULT".fmt(f),
            WaitError::EINTR => "EINTR".fmt(f),
            WaitError::EINVAL => "EINVAL".fmt(f)
        }
    }
}
<commit_msg>Epollwakeup added<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.

//use std;
use std::{fmt, error};

pub mod ctl_op {
    /// Register the target file descriptor fd on the epoll instance
    /// referred to by the file descriptor epfd and associate the
    /// event with the internal file linked to fd.
    pub const ADD: u32 = 1;
    /// Change the event event associated with the target file descriptor fd.
    pub const MOD: u32 = 2;
    /// Remove (deregister) the target file descriptor fd from the epoll
    /// instance referred to by epfd. The event is ignored and can be NULL.
    pub const DEL: u32 = 3;
}

pub mod event_type {
    /// The associated file is available for read(2) operations.
    pub const EPOLLIN:          u32 = 0x001;
    /// The associated file is available for write(2) operations.
    pub const EPOLLOUT:         u32 = 0x004;
    /// Stream socket peer closed connection, or shut down writing
    /// half of connection.
    pub const EPOLLRDHUP:       u32 = 0x2000;
    /// There is urgent data available for read(2) operations.
    pub const EPOLLPRI:         u32 = 0x002;
    /// Error condition happened on the associated file descriptor.
    /// epoll_wait(2) will always wait for this event; it is not
    /// necessary to set it in events.
    pub const EPOLLERR:         u32 = 0x008;
    /// Hang up happened on the associated file descriptor. epoll_wait(2)
    /// will always wait for this event; it is not necessary to set it
    /// in events.
    pub const EPOLLHUP:         u32 = 0x010;
    /// Sets the Edge Triggered behavior for the associated file descriptor.
    /// The default behavior for epoll is Level Triggered.
    pub const EPOLLET:          u32 = (1 << 31);
    /// Sets the one-shot behavior for the associated file descriptor.
    /// This means that after an event is pulled out with epoll_wait(2)
    /// the associated file descriptor is internally disabled and no other
    /// events will be reported by the epoll interface. The user must call
    /// epoll_ctl() with EPOLL_CTL_MOD to rearm the file descriptor with a
    /// new event mask.
    pub const EPOLLONESHOT:     u32 = (1 << 30);
    /// If EPOLLONESHOT and EPOLLET are clear and the process has the
    /// CAP_BLOCK_SUSPEND capability, ensure that the system does not
    /// enter "suspend" or "hibernate" while this event is pending or
    /// being processed.  The event is considered as being "processed"
    /// from the time when it is returned by a call to epoll_wait(2)
    /// until the next call to epoll_wait(2) on the same epoll(7) file
    /// descriptor, the closure of that file descriptor, the removal
    /// of the event file descriptor with EPOLL_CTL_DEL, or the
    /// clearing of EPOLLWAKEUP for the event file descriptor with
    /// EPOLL_CTL_MOD.
    pub const EPOLLWAKEUP:      u32 = (1 << 29);
}

#[derive(Debug, Clone)]
pub enum CreateError {
    /// Invalid value specified in flags.
    EINVAL,
    /// The per-user limit on the number of epoll instances
    /// imposed by /proc/sys/fs/epoll/max_user_instances was encountered.
    EMFILE,
    /// The system limit on the total number of open files has been reached.
    ENFILE,
    /// There was insufficient memory to create the kernel object.
    ENOMEM
}

#[derive(Debug, Clone)]
pub enum CtlError {
    /// fd is not a valid file descriptor.
    EBADF,
    /// op was EPOLL_CTL_ADD, and the supplied file descriptor fd is already
    /// registered with this epoll instance.
    EEXIST,
    /// epfd is not an epoll file descriptor, or fd is the same as epfd,
    /// or the requested operation op is not supported by this interface.
    EINVAL,
    /// op was EPOLL_CTL_MOD or EPOLL_CTL_DEL, and fd is not registered
    /// with this epoll instance.
    ENOENT,
    /// There was insufficient memory to handle the requested op control
    /// operation.
    ENOSPC,
    /// The limit imposed by /proc/sys/fs/epoll/max_user_watches was
    /// encountered while trying to register (EPOLL_CTL_ADD) a new
    /// file descriptor on an epoll instance.
    EPERM
}

#[derive(Debug, Clone)]
pub enum WaitError {
    /// epfd is not a valid file descriptor.
    EBADF,
    /// The memory area pointed to by events is not accessible
    /// with write permissions.
    EFAULT,
    /// The call was interrupted by a signal handler before
    /// either any of the requested events occurred or the timeout expired.
    EINTR,
    /// epfd is not an epoll file descriptor, or maxevents is less than
    /// or equal to zero.
    EINVAL
}

impl error::Error for CreateError {
    fn description(&self) -> &str {
        match *self {
            CreateError::EINVAL => "Invalid flags",
            CreateError::EMFILE => "/proc/sys/fs/epoll/max_user_instances limit reached",
            CreateError::ENFILE => "NOFILE limit has been reached",
            CreateError::ENOMEM => "Insufficient memory"
        }
    }
}

impl error::Error for CtlError {
    fn description(&self) -> &str {
        match *self {
            CtlError::EBADF => "Invalid file descriptor",
            CtlError::EEXIST => "File descriptor already registered",
            CtlError::EINVAL => "epoll_fd is not an epoll file descriptor",
            CtlError::ENOENT => "File descriptor not registered",
            CtlError::ENOSPC => "Insufficient memory",
            CtlError::EPERM => "/proc/sys/fs/epoll/max_user_watches limit reached"
        }
    }
}

impl error::Error for WaitError {
    fn description(&self) -> &str {
        match *self {
            WaitError::EBADF => "Invalid file descriptor",
            WaitError::EFAULT => "Memory pointed to by events is not accessible with write permissions",
            WaitError::EINTR => "Interrupted by a signal before any requested events occurred or timeout expired",
            WaitError::EINVAL => "epoll_fd not an epoll file descriptor, or maxevents is less than or equal to zero."
        }
    }
}

impl fmt::Display for CreateError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            CreateError::EINVAL => "EINVAL".fmt(f),
            CreateError::EMFILE => "EMFILE".fmt(f),
            CreateError::ENFILE => "ENFILE".fmt(f),
            CreateError::ENOMEM => "ENOMEM".fmt(f)
        }
    }
}

impl fmt::Display for CtlError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            CtlError::EBADF => "EBADF".fmt(f),
            CtlError::EEXIST => "EEXIST".fmt(f),
            CtlError::EINVAL => "EINVAL".fmt(f),
            CtlError::ENOENT => "ENOENT".fmt(f),
            CtlError::ENOSPC => "ENOSPC".fmt(f),
            CtlError::EPERM => "EPERM".fmt(f)
        }
    }
}

impl fmt::Display for WaitError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            WaitError::EBADF => "EBADF".fmt(f),
            WaitError::EFAULT => "EFAULT".fmt(f),
            WaitError::EINTR => "EINTR".fmt(f),
            WaitError::EINVAL => "EINVAL".fmt(f)
        }
    }
}
<|endoftext|>


<commit_before>//! Vectors on a plane.
use std::ops::{Add, Sub, Mul, Div, Neg};
use std::cmp::PartialEq;
use std::str::FromStr;
use std::fmt;
use std::num;

/// 2D vector in cartesian coordinates
#[derive(Debug, Clone, Copy)]
pub struct Vec2 {
    /// component of vector
    pub x: f64,
    /// component of vector
    pub y: f64,
}

impl Vec2 {
    /// Constructs a new `Vec2`.
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// // create `Vec2` with int
    /// let a = Vec2::new(10, 20);
    /// // create `Vec2` with float
    /// let b = Vec2::new(3.5, 2.5);
    /// // Supported types implemented for trait Into (with convertion to f64)
    /// ```
    pub fn new<I: Into<f64>>(x: I, y: I) -> Vec2 {
        Vec2 {
            x: x.into(),
            y: y.into(),
        }
    }
    /// Constructs a new `Vec2` from polar coordinates $(r, \theta)$.
    ///
    /// # Example
    /// ```
    /// use std::f64::consts::PI;
    /// use linal::Vec2;
    ///
    /// // calculation error
    /// let eps = 1E-15;
    /// // Create `Vec2` use polar coordinates
    /// let v = Vec2::from_polar(2.0, PI / 2.0);
    /// assert!(v.x < eps && v.y - 2.0 < eps);
    /// ```
    pub fn from_polar<I: Into<f64>>(r: I, theta: I) -> Vec2 {
        let (r, theta) = (r.into(), theta.into());
        Vec2::new(r * f64::cos(theta), r * f64::sin(theta))
    }
    /// Create a zero `Vec2`
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// // create zero `Vec2`
    /// let zero = Vec2::zero();
    /// assert_eq!(zero, Vec2::new(0, 0));
    /// ```
    pub fn zero() -> Vec2 {
        Vec2::new(0.0, 0.0)
    }
    /// Scalar product
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(1, 2);
    /// let b = Vec2::new(3, 4);
    /// // The scalar production of `a` by `b`
    /// let r = a.dot(b);
    /// assert_eq!(r, 11.0);
    /// ```
    pub fn dot(self, rhs: Vec2) -> f64 {
        self.x * rhs.x + self.y * rhs.y
    }
    /// Orthogonal vector
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(2, 2);
    /// let b = Vec2::new(2, -2);
    /// // create orthogonal vector
    /// //             y ^
    /// //               |
    /// //               |
    /// //             2 - ...... /a
    /// //               |     //  :
    /// //             1 -   //    :
    /// //    -2   -1    | //      :
    /// //  -- | -- | -- 0 -- | -- | ---->
    /// //     :      // |    1    2     x
    /// //     :    //   - -1
    /// //     :  //     |
    /// //     b/ ...... - -2
    /// let c = a.cross();
    /// assert_eq!(b, c);
    /// ```
    pub fn cross(self) -> Vec2 {
        Vec2::new(self.y, -self.x)
    }
    /// Area of parallelogramm
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(2, 0);
    /// let b = Vec2::new(0, 2);
    /// // Calculate the area of the parallelogram formed by the vectors
    /// // y ^
    /// //   |
    /// //   |
    /// // 2 b .........
    /// //   |         :
    /// // 1 -         :
    /// //   |         :
    /// //   0 -- | -- a ---->
    /// //        1    2     x
    /// let area = a.area(b);
    /// assert_eq!(area, 4.0);
    /// ```
    pub fn area(self, rhs: Vec2) -> f64 {
        self.dot(rhs.cross())
    }
    /// Vector length
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let vec = Vec2::new(2, 0);
    /// // Calculate vector length
    /// let len1 = vec.len();
    /// let len2 = (-vec.cross()).len();
    /// assert!(len1 == len2 && len1 == 2.0);
    /// ```
    pub fn len(self) -> f64 {
        self.dot(self).sqrt()
    }
    /// Unary vector, co-directed with given
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(2, 0);
    /// // Calculate unary vector from `a`
    /// let b = a.ort();
    /// assert_eq!(b, Vec2::new(1, 0));
    /// ```
    pub fn ort(self) -> Vec2 {
        self / self.len()
    }
    /// Squares of the vector coordinates
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(2, 3);
    /// let b = Vec2::new(4, 9);
    /// // Calculate squre of `a`
    /// let c = a.sqr();
    /// assert_eq!(b, c);
    /// ```
    pub fn sqr(self) -> Vec2 {
        self * self
    }
    /// Square root of vector coordinates
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(2, 3);
    /// let b = Vec2::new(4, 9);
    /// // Calculate squre root of `b`
    /// let c = b.sqrt();
    /// assert_eq!(a, c);
    /// ```
    pub fn sqrt(self) -> Vec2 {
        Vec2::new(self.x.sqrt(), self.y.sqrt())
    }
    /// Constructs dual basis for given.
    ///
    /// Dual basis $(\vec{b}_1, \vec{b}_2)$ for basis $(\vec{a}_1, \vec{a}_2)$ satisfies relation
    /// $$\vec{a}_i \cdot \vec{b}_j = \delta_{ij}$$
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a1 = Vec2::new(2, 0);
    /// let a2 = Vec2::new(3, 4);
    ///
    /// let (b1, b2) = Vec2::dual_basis((a1, a2));
    /// assert_eq!(b1, Vec2::new(0.5, -0.375));
    /// assert_eq!(b2, Vec2::new(0.0, 0.25));
    /// ```
    pub fn dual_basis(basis: (Vec2, Vec2)) -> (Vec2, Vec2) {
        let (a, b) = basis;
        let area = a.area(b);
        (b.cross() / area, -a.cross() / area)
    }
}

impl Add for Vec2 {
    type Output = Self;

    fn add(self, _rhs: Self) -> Self {
        Vec2::new(self.x + _rhs.x, self.y + _rhs.y)
    }
}

impl Sub for Vec2 {
    type Output = Self;

    fn sub(self, _rhs: Self) -> Self {
        Vec2::new(self.x - _rhs.x, self.y - _rhs.y)
    }
}

impl Mul for Vec2 {
    type Output = Self;

    fn mul(self, _rhs: Vec2) -> Vec2 {
        Vec2::new(self.x * _rhs.x, self.y * _rhs.y)
    }
}

impl<I: Into<f64>> Mul<I> for Vec2 {
    type Output = Self;

    fn mul(self, _rhs: I) -> Vec2 {
        let _rhs = _rhs.into();
        Vec2::new(self.x * _rhs, self.y * _rhs)
    }
}

impl<I: Into<f64>> Div<I> for Vec2 {
    type Output = Self;

    fn div(self, _rhs: I) -> Vec2 {
        let _rhs = _rhs.into();
        if _rhs == 0.0 {
            panic!("Can't divide by zero!");
        }
        Vec2::new(self.x / _rhs, self.y / _rhs)
    }
}

impl Neg for Vec2 {
    type Output = Self;

    fn neg(self) -> Self {
        Self::new(-self.x, -self.y)
    }
}

impl PartialEq for Vec2 {
    fn eq(&self, other: &Self) -> bool {
        self.x == other.x && self.y == other.y
    }
}

impl fmt::Display for Vec2 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", self.x, self.y)
    }
}

impl FromStr for Vec2 {
    type Err = num::ParseFloatError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let words: Vec<&str> = s.split_whitespace().collect();
        let x: f64 = try!(words[0].parse());
        let y: f64 = try!(words[1].parse());
        Ok(Self::new(x, y))
    }
}

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

    #[test]
    fn vec2_mul() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(3, 6);
        let r = a * 3;
        assert_eq!(r, b);
    }

    #[test]
    #[should_panic]
    fn vec2_div() {
        let a = Vec2::new(1, 2);
        let _ = a / 0.0;
    }

    #[test]
    fn vec2_from_polar() {
        let a = Vec2::new(3, 4);
        let b = Vec2::from_polar(5.0, f64::atan2(4.0, 3.0));
        assert!((a - b).len() < 1e-10);
    }

    #[test]
    fn vec2_add() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-3, 6);
        let c = Vec2::new(-2, 8);
        assert_eq!(a + b, c);
    }

    #[test]
    fn vec2_sub() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-3, 6);
        let c = Vec2::new(4, -4);
        assert_eq!(a - b, c);
    }

    #[test]
    fn vec2_dot() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-3, 6);
        let c = 9.0;
        assert_eq!(a.dot(b), c);
        assert_eq!(b.dot(a), c);
    }

    #[test]
    fn vec2_area() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-3, 6);
        let c = 12.0;
        assert_eq!(a.area(b), c);
        assert_eq!(b.area(a), -c);
    }

    #[test]
    fn vec2_cross_z() {
        let a = Vec2::new(1, 2);
        let b = 2.0;
        let c = Vec2::new(4, -2);
        assert_eq!(a.cross() * b, c);
    }

    #[test]
    fn vec2_neg() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-1, -2);
        assert_eq!(-a, b);
    }

    #[test]
    fn vec2_parse() {
        let a: Vec2 = "1 2".parse().unwrap();
        assert_eq!(a, Vec2::new(1, 2));
    }
}
<commit_msg>[fix] ascii art<commit_after>//! Vectors on a plane.
use std::ops::{Add, Sub, Mul, Div, Neg};
use std::cmp::PartialEq;
use std::str::FromStr;
use std::fmt;
use std::num;

/// 2D vector in cartesian coordinates
#[derive(Debug, Clone, Copy)]
pub struct Vec2 {
    /// component of vector
    pub x: f64,
    /// component of vector
    pub y: f64,
}

impl Vec2 {
    /// Constructs a new `Vec2`.
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// // create `Vec2` with int
    /// let a = Vec2::new(10, 20);
    /// // create `Vec2` with float
    /// let b = Vec2::new(3.5, 2.5);
    /// // Supported types implemented for trait Into (with convertion to f64)
    /// ```
    pub fn new<I: Into<f64>>(x: I, y: I) -> Vec2 {
        Vec2 {
            x: x.into(),
            y: y.into(),
        }
    }
    /// Constructs a new `Vec2` from polar coordinates $(r, \theta)$.
    ///
    /// # Example
    /// ```
    /// use std::f64::consts::PI;
    /// use linal::Vec2;
    ///
    /// // calculation error
    /// let eps = 1E-15;
    /// // Create `Vec2` use polar coordinates
    /// let v = Vec2::from_polar(2.0, PI / 2.0);
    /// assert!(v.x < eps && v.y - 2.0 < eps);
    /// ```
    pub fn from_polar<I: Into<f64>>(r: I, theta: I) -> Vec2 {
        let (r, theta) = (r.into(), theta.into());
        Vec2::new(r * f64::cos(theta), r * f64::sin(theta))
    }
    /// Create a zero `Vec2`
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// // create zero `Vec2`
    /// let zero = Vec2::zero();
    /// assert_eq!(zero, Vec2::new(0, 0));
    /// ```
    pub fn zero() -> Vec2 {
        Vec2::new(0.0, 0.0)
    }
    /// Scalar product
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(1, 2);
    /// let b = Vec2::new(3, 4);
    /// // The scalar production of `a` by `b`
    /// let r = a.dot(b);
    /// assert_eq!(r, 11.0);
    /// ```
    pub fn dot(self, rhs: Vec2) -> f64 {
        self.x * rhs.x + self.y * rhs.y
    }
    /// Orthogonal vector
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(2, 2);
    /// let b = Vec2::new(2, -2);
    /// // create orthogonal vector with same length
    /// // rotated in clockwise direction
    /// //             y ^
    /// //               |
    /// //               |
    /// //             2 - ...... /a
    /// //               |     //  :
    /// //             1 -   //    :
    /// //    -2   -1    | //      :
    /// //  -- | -- | -- 0 -- | -- | ---->
    /// //               | \\   1  : 2     x
    /// //               - -1\\    :
    /// //               |     \\  :
    /// //               - -2.....\b
    /// let c = a.cross();
    /// assert_eq!(b, c);
    /// ```
    pub fn cross(self) -> Vec2 {
        Vec2::new(self.y, -self.x)
    }
    /// Area of parallelogramm
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(2, 0);
    /// let b = Vec2::new(1, 2);
    /// // Calculate the area of the parallelogram formed by the vectors
    /// // y ^
    /// //   |
    /// //   |
    /// // 2 -    b .........
    /// //   |   /#########/
    /// // 1 -  /#  area #/
    /// //   | /#########/
    /// //   0 -- | -- a ---->
    /// //        1    2     x
    /// let area = a.area(b);
    /// assert_eq!(area, 4.0);
    /// ```
    pub fn area(self, rhs: Vec2) -> f64 {
        self.dot(rhs.cross())
    }
    /// Vector length
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let vec = Vec2::new(2, 0);
    /// // Calculate vector length
    /// let len1 = vec.len();
    /// let len2 = (-vec.cross()).len();
    /// assert!(len1 == len2 && len1 == 2.0);
    /// ```
    pub fn len(self) -> f64 {
        self.dot(self).sqrt()
    }
    /// Unary vector, co-directed with given
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(2, 0);
    /// // Calculate unary vector from `a`
    /// let b = a.ort();
    /// assert_eq!(b, Vec2::new(1, 0));
    /// ```
    pub fn ort(self) -> Vec2 {
        self / self.len()
    }
    /// Squares of the vector coordinates
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(2, 3);
    /// let b = Vec2::new(4, 9);
    /// // Calculate squre of `a`
    /// let c = a.sqr();
    /// assert_eq!(b, c);
    /// ```
    pub fn sqr(self) -> Vec2 {
        self * self
    }
    /// Square root of vector coordinates
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(2, 3);
    /// let b = Vec2::new(4, 9);
    /// // Calculate squre root of `b`
    /// let c = b.sqrt();
    /// assert_eq!(a, c);
    /// ```
    pub fn sqrt(self) -> Vec2 {
        Vec2::new(self.x.sqrt(), self.y.sqrt())
    }
    /// Constructs dual basis for given.
    ///
    /// Dual basis $(\vec{b}_1, \vec{b}_2)$ for basis $(\vec{a}_1, \vec{a}_2)$ satisfies relation
    /// $$\vec{a}_i \cdot \vec{b}_j = \delta_{ij}$$
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a1 = Vec2::new(2, 0);
    /// let a2 = Vec2::new(3, 4);
    ///
    /// let (b1, b2) = Vec2::dual_basis((a1, a2));
    /// assert_eq!(b1, Vec2::new(0.5, -0.375));
    /// assert_eq!(b2, Vec2::new(0.0, 0.25));
    /// ```
    pub fn dual_basis(basis: (Vec2, Vec2)) -> (Vec2, Vec2) {
        let (a, b) = basis;
        let area = a.area(b);
        (b.cross() / area, -a.cross() / area)
    }
}

impl Add for Vec2 {
    type Output = Self;

    fn add(self, _rhs: Self) -> Self {
        Vec2::new(self.x + _rhs.x, self.y + _rhs.y)
    }
}

impl Sub for Vec2 {
    type Output = Self;

    fn sub(self, _rhs: Self) -> Self {
        Vec2::new(self.x - _rhs.x, self.y - _rhs.y)
    }
}

impl Mul for Vec2 {
    type Output = Self;

    fn mul(self, _rhs: Vec2) -> Vec2 {
        Vec2::new(self.x * _rhs.x, self.y * _rhs.y)
    }
}

impl<I: Into<f64>> Mul<I> for Vec2 {
    type Output = Self;

    fn mul(self, _rhs: I) -> Vec2 {
        let _rhs = _rhs.into();
        Vec2::new(self.x * _rhs, self.y * _rhs)
    }
}

impl<I: Into<f64>> Div<I> for Vec2 {
    type Output = Self;

    fn div(self, _rhs: I) -> Vec2 {
        let _rhs = _rhs.into();
        if _rhs == 0.0 {
            panic!("Can't divide by zero!");
        }
        Vec2::new(self.x / _rhs, self.y / _rhs)
    }
}

impl Neg for Vec2 {
    type Output = Self;

    fn neg(self) -> Self {
        Self::new(-self.x, -self.y)
    }
}

impl PartialEq for Vec2 {
    fn eq(&self, other: &Self) -> bool {
        self.x == other.x && self.y == other.y
    }
}

impl fmt::Display for Vec2 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", self.x, self.y)
    }
}

impl FromStr for Vec2 {
    type Err = num::ParseFloatError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let words: Vec<&str> = s.split_whitespace().collect();
        let x: f64 = try!(words[0].parse());
        let y: f64 = try!(words[1].parse());
        Ok(Self::new(x, y))
    }
}

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

    #[test]
    fn vec2_mul() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(3, 6);
        let r = a * 3;
        assert_eq!(r, b);
    }

    #[test]
    #[should_panic]
    fn vec2_div() {
        let a = Vec2::new(1, 2);
        let _ = a / 0.0;
    }

    #[test]
    fn vec2_from_polar() {
        let a = Vec2::new(3, 4);
        let b = Vec2::from_polar(5.0, f64::atan2(4.0, 3.0));
        assert!((a - b).len() < 1e-10);
    }

    #[test]
    fn vec2_add() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-3, 6);
        let c = Vec2::new(-2, 8);
        assert_eq!(a + b, c);
    }

    #[test]
    fn vec2_sub() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-3, 6);
        let c = Vec2::new(4, -4);
        assert_eq!(a - b, c);
    }

    #[test]
    fn vec2_dot() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-3, 6);
        let c = 9.0;
        assert_eq!(a.dot(b), c);
        assert_eq!(b.dot(a), c);
    }

    #[test]
    fn vec2_area() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-3, 6);
        let c = 12.0;
        assert_eq!(a.area(b), c);
        assert_eq!(b.area(a), -c);
    }

    #[test]
    fn vec2_cross_z() {
        let a = Vec2::new(1, 2);
        let b = 2.0;
        let c = Vec2::new(4, -2);
        assert_eq!(a.cross() * b, c);
    }

    #[test]
    fn vec2_neg() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-1, -2);
        assert_eq!(-a, b);
    }

    #[test]
    fn vec2_parse() {
        let a: Vec2 = "1 2".parse().unwrap();
        assert_eq!(a, Vec2::new(1, 2));
    }
}
<|endoftext|>


<commit_before>use ffi::bindings::*;
use std::marker::PhantomData;
use std::os::raw::c_uint;
use std::slice;
use std::mem;
use device::Device;
use struct_wrappers::unit::*;
use enum_wrappers::unit::*;
use enums::unit::*;
use error::*;
use NVML;

/**
Struct that represents a unit.

Obtain a `Unit` with the various methods available to you on the `NVML`
struct.

I don't know what a unit is, but inferring from the docs leads me to believe
it's some kind of high-end something-or-other that 99% of users won't know
about either. That being said, I'm wrapping this whole library, so here you go.

Rust's lifetimes will ensure that the NVML instance this `Unit` was created from
is not allowed to be shutdown until this `Unit` is dropped, meaning you shouldn't
have to worry about calls returning `Uninitialized` errors.
*/
// TODO: Use compiletest to ensure lifetime guarantees
#[derive(Debug)]
pub struct Unit<'nvml> {
    unit: nvmlUnit_t,
    _phantom: PhantomData<&'nvml NVML>,
}

unsafe impl<'nvml> Send for Unit<'nvml> {}
unsafe impl<'nvml> Sync for Unit<'nvml> {}

impl<'nvml> From<nvmlUnit_t> for Unit<'nvml> {
    fn from(unit: nvmlUnit_t) -> Self {
        Unit {
            unit,
            _phantom: PhantomData,
        }
    }
}

impl<'nvml> Unit<'nvml> {
    /**
    Gets the set of GPU devices that are attached to this `Unit`.

    **I do not have the hardware to test this call. Verify for yourself that it
    works before you use it**. If it works, please let me know; if it doesn't,
    I would love a PR. If NVML is sane this should work, but NVIDIA's docs
    on this call are _anything_ but clear.

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `InvalidArg`, if the unit is invalid
    * `Unknown`, on any unexpected error

    # Device Support
    For S-class products.
    */
    // Checked against local
    #[inline]
    pub fn devices(&self) -> Result<Vec<Device>> {
        unsafe {
            let mut count: c_uint = match self.device_count()? {
                0 => return Ok(vec![]),
                value => value,
            };
            let mut devices: Vec<nvmlDevice_t> = vec![mem::zeroed(); count as usize];

            // Indexing 0 here is safe because we make sure `count` is not 0 above
            nvml_try(nvmlUnitGetDevices(self.unit, &mut count, &mut devices[0]))?;
            Ok(devices.iter()
                      .map(|d| Device::from(*d))
                      .collect())
        }
    }

    /**
    Gets the count of GPU devices that are attached to this `Unit`.

    **I do not have the hardware to test this call. Verify for yourself that it
    works before you use it**. If it works, please let me know; if it doesn't,
    I would love a PR. If NVML is sane this should work, but NVIDIA's docs
    on this call are _anything_ but clear.

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `InvalidArg`, if the unit is invalid
    * `Unknown`, on any unexpected error

    # Device Support
    For S-class products.
    */
    #[inline]
    pub fn device_count(&self) -> Result<u32> {
        unsafe {
            // NVIDIA doesn't even say that `count` will be set to the count if
            // `InsufficientSize` is returned. But we can assume sanity, right?
            let mut count: c_uint = 0;
            let devices: [nvmlDevice_t; 1] = [mem::zeroed()];

            match nvmlUnitGetDevices(self.unit, &mut count, &mut devices[0]) {
                // I'm assuming this is right... ?
                nvmlReturn_t::NVML_SUCCESS => Ok(0),
                // Also assuming this is right... ?
                nvmlReturn_t::NVML_ERROR_INSUFFICIENT_SIZE => Ok(count),
                // We know that this will be an error
                other => nvml_try(other).map(|_| 0),
            }
        }
    }

    /**
    Gets fan information for this `Unit` (fan count and state + speed for each).

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `InvalidArg`, if the unit is invalid
    * `NotSupported`, if this is not an S-class product
    * `Unknown`, on any unexpected error

    # Device Support
    For S-class products.
    */
    // Checked against local
    #[inline]
    pub fn fan_info(&self) -> Result<UnitFansInfo> {
        unsafe {
            let mut fans_info: nvmlUnitFanSpeeds_t = mem::zeroed();
            nvml_try(nvmlUnitGetFanSpeedInfo(self.unit, &mut fans_info))?;

            Ok(fans_info.into())
        }
    }

    /**
    Gets the LED state associated with this `Unit`.

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `InvalidArg`, if the unit is invalid
    * `NotSupported`, if this is not an S-class product
    * `Utf8Error`, if the string obtained from the C function is not valid Utf8
    * `Unknown`, on any unexpected error

    # Device Support
    For S-class products.
    */
    // Checked against local
    #[inline]
    pub fn led_state(&self) -> Result<UnitLedState> {
        unsafe {
            let mut state: nvmlLedState_t = mem::zeroed();
            nvml_try(nvmlUnitGetLedState(self.unit, &mut state))?;

            Ok(UnitLedState::try_from(state)?)
        }
    }

    /**
    Gets the PSU stats for this `Unit`.

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `InvalidArg`, if the unit is invalid
    * `NotSupported`, if this is not an S-class product
    * `Utf8Error`, if the string obtained from the C function is not valid Utf8
    * `Unknown`, on any unexpected error

    # Device Support
    For S-class products.
    */
    // Checked against local
    #[inline]
    pub fn psu_info(&self) -> Result<UnitPsuInfo> {
        unsafe {
            let mut info: nvmlPSUInfo_t = mem::zeroed();
            nvml_try(nvmlUnitGetPsuInfo(self.unit, &mut info))?;

            Ok(UnitPsuInfo::try_from(info)?)
        }
    }

    /**
    Gets the temperature for the specified `UnitTemperatureReading`, in °C.

    Available readings depend on the product.

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `InvalidArg`, if the unit is invalid
    * `NotSupported`, if this is not an S-class product
    * `Unknown`, on any unexpected error

    # Device Support
    For S-class products. Available readings depend on the product.
    */
    // Checked against local
    #[inline]
    pub fn temperature(&self, reading_type: UnitTemperatureReading) -> Result<u32> {
        unsafe {
            let mut temp: c_uint = mem::zeroed();
            nvml_try(nvmlUnitGetTemperature(self.unit, reading_type as c_uint, &mut temp))?;

            Ok(temp as u32)
        }
    }

    /**
    Gets the static information associated with this `Unit`.

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `InvalidArg`, if the unit is invalid
    * `Utf8Error`, if the string obtained from the C function is not valid Utf8

    # Device Support
    For S-class products.
    */
    // Checked against local
    #[inline]
    pub fn info(&self) -> Result<UnitInfo> {
        unsafe {
            let mut info: nvmlUnitInfo_t = mem::zeroed();
            nvml_try(nvmlUnitGetUnitInfo(self.unit, &mut info))?;

            Ok(UnitInfo::try_from(info)?)
        }
    }

    // Unit commands starting here

    /**
    Sets the LED color for this `Unit`.

    Requires root/admin permissions. This operation takes effect immediately.

    Note: Current S-class products don't provide unique LEDs for each unit. As such,
    both front and back LEDs will be toggled in unison regardless of which unit is
    specified with this method (aka the `Unit` represented by this struct).

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `InvalidArg`, if the unit is invalid
    * `NotSupported`, if this is not an S-class product
    * `NoPermission`, if the user doesn't have permission to perform this operation
    * `Unknown`, on any unexpected error

    # Device Support
    For S-class products.
    */
    // checked against local
    #[inline]
    pub fn set_led_color(&mut self, color: LedColor) -> Result<()> {
        unsafe {
            nvml_try(nvmlUnitSetLedState(self.unit, color.into_c()))
        }
    }

    /// Consume the struct and obtain the raw unit handle that it contains.
    #[inline]
    pub fn into_raw(self) -> nvmlUnit_t {
        self.unit
    }

    /// Obtain a reference to the raw unit handle contained in the struct.
    #[inline]
    pub fn as_raw(&self) -> &nvmlUnit_t {
        &(self.unit)
    }

    /// Obtain a mutable reference to the raw unit handle contained in the struct.
    #[inline]
    pub fn as_mut_raw(&mut self) -> &mut nvmlUnit_t {
        &mut (self.unit)
    }

    /// Sometimes necessary for C interop. Use carefully.
    #[inline]
    pub unsafe fn unsafe_raw(&self) -> nvmlUnit_t {
        self.unit
    }
}
<commit_msg>Revised array strategy for `unit` method<commit_after>use ffi::bindings::*;
use std::marker::PhantomData;
use std::os::raw::c_uint;
use std::slice;
use std::mem;
use device::Device;
use struct_wrappers::unit::*;
use enum_wrappers::unit::*;
use enums::unit::*;
use error::*;
use NVML;

/**
Struct that represents a unit.

Obtain a `Unit` with the various methods available to you on the `NVML`
struct.

I don't know what a unit is, but inferring from the docs leads me to believe
it's some kind of high-end something-or-other that 99% of users won't know
about either. That being said, I'm wrapping this whole library, so here you go.

Rust's lifetimes will ensure that the NVML instance this `Unit` was created from
is not allowed to be shutdown until this `Unit` is dropped, meaning you shouldn't
have to worry about calls returning `Uninitialized` errors.
*/
// TODO: Use compiletest to ensure lifetime guarantees
#[derive(Debug)]
pub struct Unit<'nvml> {
    unit: nvmlUnit_t,
    _phantom: PhantomData<&'nvml NVML>,
}

unsafe impl<'nvml> Send for Unit<'nvml> {}
unsafe impl<'nvml> Sync for Unit<'nvml> {}

impl<'nvml> From<nvmlUnit_t> for Unit<'nvml> {
    fn from(unit: nvmlUnit_t) -> Self {
        Unit {
            unit,
            _phantom: PhantomData,
        }
    }
}

impl<'nvml> Unit<'nvml> {
    /**
    Gets the set of GPU devices that are attached to this `Unit`.

    **I do not have the hardware to test this call. Verify for yourself that it
    works before you use it**. If it works, please let me know; if it doesn't,
    I would love a PR. If NVML is sane this should work, but NVIDIA's docs
    on this call are _anything_ but clear.

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `InvalidArg`, if the unit is invalid
    * `Unknown`, on any unexpected error

    # Device Support
    For S-class products.
    */
    // Checked against local
    #[inline]
    pub fn devices(&self) -> Result<Vec<Device>> {
        unsafe {
            let mut count: c_uint = match self.device_count()? {
                0 => return Ok(vec![]),
                value => value,
            };
            let mut devices: Vec<nvmlDevice_t> = vec![mem::zeroed(); count as usize];

            // Indexing 0 here is safe because we make sure `count` is not 0 above
            nvml_try(nvmlUnitGetDevices(self.unit, &mut count, &mut devices[0]))?;
            Ok(devices.iter()
                      .map(|d| Device::from(*d))
                      .collect())
        }
    }

    /**
    Gets the count of GPU devices that are attached to this `Unit`.

    **I do not have the hardware to test this call. Verify for yourself that it
    works before you use it**. If it works, please let me know; if it doesn't,
    I would love a PR. If NVML is sane this should work, but NVIDIA's docs
    on this call are _anything_ but clear.

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `InvalidArg`, if the unit is invalid
    * `Unknown`, on any unexpected error

    # Device Support
    For S-class products.
    */
    #[inline]
    pub fn device_count(&self) -> Result<u32> {
        unsafe {
            // NVIDIA doesn't even say that `count` will be set to the count if
            // `InsufficientSize` is returned. But we can assume sanity, right?
            //
            // The idea here is:
            // If there are 0 devices, NVML_SUCCESS is returned, `count` is set
            //   to 0. We return count, all good.
            // If there is 1 device, NVML_SUCCESS is returned, `count` remains
            //   0. We return count, all good.
            // If there are >= 2 devices, NVML_INSUFFICIENT_SIZE is returned.
            //  `count` is theoretically set to the actual count, and we
            //   return it.
            let mut count: c_uint = 1;
            let mut devices: [nvmlDevice_t; 1] = [mem::zeroed()];

            nvmlUnitGetDevices(self.unit, &mut count, &mut devices[0])?;
            Ok(count)
        }
    }

    /**
    Gets fan information for this `Unit` (fan count and state + speed for each).

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `InvalidArg`, if the unit is invalid
    * `NotSupported`, if this is not an S-class product
    * `Unknown`, on any unexpected error

    # Device Support
    For S-class products.
    */
    // Checked against local
    #[inline]
    pub fn fan_info(&self) -> Result<UnitFansInfo> {
        unsafe {
            let mut fans_info: nvmlUnitFanSpeeds_t = mem::zeroed();
            nvml_try(nvmlUnitGetFanSpeedInfo(self.unit, &mut fans_info))?;

            Ok(fans_info.into())
        }
    }

    /**
    Gets the LED state associated with this `Unit`.

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `InvalidArg`, if the unit is invalid
    * `NotSupported`, if this is not an S-class product
    * `Utf8Error`, if the string obtained from the C function is not valid Utf8
    * `Unknown`, on any unexpected error

    # Device Support
    For S-class products.
    */
    // Checked against local
    #[inline]
    pub fn led_state(&self) -> Result<UnitLedState> {
        unsafe {
            let mut state: nvmlLedState_t = mem::zeroed();
            nvml_try(nvmlUnitGetLedState(self.unit, &mut state))?;

            Ok(UnitLedState::try_from(state)?)
        }
    }

    /**
    Gets the PSU stats for this `Unit`.

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `InvalidArg`, if the unit is invalid
    * `NotSupported`, if this is not an S-class product
    * `Utf8Error`, if the string obtained from the C function is not valid Utf8
    * `Unknown`, on any unexpected error

    # Device Support
    For S-class products.
    */
    // Checked against local
    #[inline]
    pub fn psu_info(&self) -> Result<UnitPsuInfo> {
        unsafe {
            let mut info: nvmlPSUInfo_t = mem::zeroed();
            nvml_try(nvmlUnitGetPsuInfo(self.unit, &mut info))?;

            Ok(UnitPsuInfo::try_from(info)?)
        }
    }

    /**
    Gets the temperature for the specified `UnitTemperatureReading`, in °C.

    Available readings depend on the product.

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `InvalidArg`, if the unit is invalid
    * `NotSupported`, if this is not an S-class product
    * `Unknown`, on any unexpected error

    # Device Support
    For S-class products. Available readings depend on the product.
    */
    // Checked against local
    #[inline]
    pub fn temperature(&self, reading_type: UnitTemperatureReading) -> Result<u32> {
        unsafe {
            let mut temp: c_uint = mem::zeroed();
            nvml_try(nvmlUnitGetTemperature(self.unit, reading_type as c_uint, &mut temp))?;

            Ok(temp as u32)
        }
    }

    /**
    Gets the static information associated with this `Unit`.

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `InvalidArg`, if the unit is invalid
    * `Utf8Error`, if the string obtained from the C function is not valid Utf8

    # Device Support
    For S-class products.
    */
    // Checked against local
    #[inline]
    pub fn info(&self) -> Result<UnitInfo> {
        unsafe {
            let mut info: nvmlUnitInfo_t = mem::zeroed();
            nvml_try(nvmlUnitGetUnitInfo(self.unit, &mut info))?;

            Ok(UnitInfo::try_from(info)?)
        }
    }

    // Unit commands starting here

    /**
    Sets the LED color for this `Unit`.

    Requires root/admin permissions. This operation takes effect immediately.

    Note: Current S-class products don't provide unique LEDs for each unit. As such,
    both front and back LEDs will be toggled in unison regardless of which unit is
    specified with this method (aka the `Unit` represented by this struct).

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `InvalidArg`, if the unit is invalid
    * `NotSupported`, if this is not an S-class product
    * `NoPermission`, if the user doesn't have permission to perform this operation
    * `Unknown`, on any unexpected error

    # Device Support
    For S-class products.
    */
    // checked against local
    #[inline]
    pub fn set_led_color(&mut self, color: LedColor) -> Result<()> {
        unsafe {
            nvml_try(nvmlUnitSetLedState(self.unit, color.into_c()))
        }
    }

    /// Consume the struct and obtain the raw unit handle that it contains.
    #[inline]
    pub fn into_raw(self) -> nvmlUnit_t {
        self.unit
    }

    /// Obtain a reference to the raw unit handle contained in the struct.
    #[inline]
    pub fn as_raw(&self) -> &nvmlUnit_t {
        &(self.unit)
    }

    /// Obtain a mutable reference to the raw unit handle contained in the struct.
    #[inline]
    pub fn as_mut_raw(&mut self) -> &mut nvmlUnit_t {
        &mut (self.unit)
    }

    /// Sometimes necessary for C interop. Use carefully.
    #[inline]
    pub unsafe fn unsafe_raw(&self) -> nvmlUnit_t {
        self.unit
    }
}
<|endoftext|>


<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,
}

#[derive(Debug)]
enum Inner {
    Unsupported,
    Disabled,
    Captured(Mutex<Capture>),
}

#[derive(Debug)]
struct Capture {
    actual_start: usize,
    resolved: bool,
    frames: Vec<BacktraceFrame>,
}

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

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

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

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

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

        let mut dbg = fmt.debug_list();

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

        dbg.finish()
    }
}

impl fmt::Debug for BacktraceFrame {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.debug_list().entries(&self.symbols).finish()
    }
}

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

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

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

        dbg.finish()
    }
}

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

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

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

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

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

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

        Backtrace { inner }
    }

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

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

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

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

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

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

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

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

    #[test]
    fn debug_backtrace_fmt() {
        let bt = Backtrace::capture();
        eprintln!("uncaptured: {:?}", bt);
        let bt = Backtrace::force_capture();
        eprintln!("captured: {:?}", bt);
        eprintln!("display print: {}", bt);
        eprintln!("resolved: {:?}", bt);
        unimplemented!();
    }
}
<commit_msg>remove unnecessary derives<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 mut dbg = fmt.debug_list();

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

        dbg.finish()
    }
}

impl fmt::Debug for BacktraceFrame {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.debug_list().entries(&self.symbols).finish()
    }
}

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

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

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

        dbg.finish()
    }
}

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

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

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

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

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

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

        Backtrace { inner }
    }

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

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

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

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

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

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

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

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

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