Skip to main content

nu_utils/
location.rs

1use serde::{Deserialize, Serialize};
2use std::{
3    borrow::Cow,
4    fmt::{self, Display},
5};
6
7/// A serializable source code location.
8///
9/// This is meant to be a drop in replacement for [`std::panic::Location`]
10/// with the added benefit that it implements [`Serialize`] and [`Deserialize`].
11///
12/// In practice, this is useful when you want to capture caller information
13/// and store it, send it across process boundaries, or include it in serialized data.
14///
15/// For behavior and semantics, see [`std::panic::Location`].
16#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
17pub struct Location {
18    file: Cow<'static, str>,
19    line: u32,
20    column: u32,
21}
22
23impl Location {
24    /// Returns the caller location.
25    ///
26    /// See [`std::panic::Location::caller`] for details.
27    #[track_caller]
28    pub const fn caller() -> Self {
29        let location = std::panic::Location::caller();
30        Self {
31            file: Cow::Borrowed(location.file()),
32            line: location.line(),
33            column: location.column(),
34        }
35    }
36
37    /// Returns the file name.
38    ///
39    /// See [`std::panic::Location::file`] for details.
40    pub const fn file(&self) -> &str {
41        match &self.file {
42            Cow::Borrowed(s) => s,
43            Cow::Owned(s) => s.as_str(),
44        }
45    }
46
47    /// Returns the column number.
48    ///
49    /// See [`std::panic::Location::column`] for details.
50    pub const fn column(&self) -> u32 {
51        self.column
52    }
53
54    /// Returns the line number.
55    ///
56    /// See [`std::panic::Location::line`] for details.
57    pub const fn line(&self) -> u32 {
58        self.line
59    }
60}
61
62/// Converts a static [`std::panic::Location`] into a [`Location`].
63///
64/// `std::panic::Location::caller()` returns a `'static` location, so this
65/// conversion can borrow the file path without allocating.
66impl From<&'static std::panic::Location<'static>> for Location {
67    fn from(location: &'static std::panic::Location<'static>) -> Self {
68        Self {
69            file: Cow::Borrowed(location.file()),
70            line: location.line(),
71            column: location.column(),
72        }
73    }
74}
75
76impl Display for Location {
77    /// Formats this location as `file:line:column`.
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        write!(f, "{}:{}:{}", self.file, self.line, self.column)
80    }
81}