Skip to content

Commit

Permalink
feat: add as_borrowed
Browse files Browse the repository at this point in the history
  • Loading branch information
polazarus committed Nov 18, 2024
1 parent e0ef4be commit 416e20c
Show file tree
Hide file tree
Showing 8 changed files with 238 additions and 49 deletions.
24 changes: 24 additions & 0 deletions src/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,30 @@ where
}
}

/// Returns the borrowed slice if this `HipByt` is actually borrowed, `None`
/// otherwise.
///
/// # Examples
///
/// ```
/// # use hipstr::HipByt;
/// static SEQ: &[u8] = &[1 ,2, 3];
/// let s = HipByt::borrowed(SEQ);
/// let c: Option<&'static [u8]> = s.as_borrowed();
/// assert_eq!(c, Some(SEQ));
/// assert!(std::ptr::eq(SEQ, c.unwrap()));
///
/// let s2 = HipByt::from(SEQ);
/// assert!(s2.as_borrowed().is_none());
/// ```
#[inline]
pub const fn as_borrowed(&self) -> Option<&'borrow [u8]> {
match self.split() {
RawSplit::Allocated(_) | RawSplit::Inline(_) => None,
RawSplit::Borrowed(borrowed) => Some(borrowed.as_slice()),
}
}

/// Returns `true` if this `HipByt` is a shared heap-allocated byte sequence, `false` otherwise.
///
/// # Examples
Expand Down
21 changes: 20 additions & 1 deletion src/bytes/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,9 @@ fn test_clone_drop() {
fn test_into_borrowed() {
// static
let a = H::borrowed(ABC);
assert_eq!(a.into_borrowed(), Ok(ABC));
let s = a.into_borrowed().unwrap();
assert_eq!(s, ABC);
assert!(core::ptr::eq(s, ABC));

// inline
let a = H::from(ABC);
Expand All @@ -254,6 +256,23 @@ fn test_into_borrowed() {
assert_eq!(a.into_borrowed(), Err(b));
}

#[test]
fn test_as_borrowed() {
// borrowed
let a = H::borrowed(ABC);
let b = a.as_borrowed().unwrap();
assert_eq!(b, ABC);
assert!(core::ptr::eq(b, ABC));

// inline
let a = H::from(ABC);
assert_eq!(a.as_borrowed(), None);

// heap
let a = H::from(MEDIUM);
assert_eq!(a.as_borrowed(), None);
}

#[test]
fn test_as_mut_slice() {
// static
Expand Down
29 changes: 29 additions & 0 deletions src/os_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,35 @@ where
.map_err(Self)
}

/// Returns the borrowed slice if this `HipOsStr` is actually borrowed,
/// `None` otherwise.
///
/// # Examples
///
/// ```
/// # use hipstr::HipOsStr;
/// # use std::ffi::OsStr;
/// let abc: &'static OsStr = OsStr::new("abc");
/// let s = HipOsStr::borrowed(abc);
/// let c: Option<&'static OsStr> = s.as_borrowed();
/// assert_eq!(c, Some(abc));
/// assert!(std::ptr::eq(abc, c.unwrap()));
///
/// let s2 = HipOsStr::from(abc);
/// assert!(s2.as_borrowed().is_none());
/// ```
#[inline]
pub const fn as_borrowed(&self) -> Option<&'borrow OsStr> {
match self.0.as_borrowed() {
Some(slice) => {
// SAFETY: type invariant
// transmute to be "const"
Some(unsafe { core::mem::transmute(slice) })
}
None => None,
}
}

/// Returns the length of this `HipOsStr`, in bytes, not [`char`]s or
/// graphemes. In other words, it might not be what a human considers the
/// length of the string.
Expand Down
24 changes: 22 additions & 2 deletions src/os_string/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@ fn test_clone() {
}

#[test]
fn test_into_static() {
// static
fn test_into_borrowed() {
// borrowed
let a = HipOsStr::borrowed("abc");
assert_eq!(a.into_borrowed(), Ok("abc".as_ref()));

Expand All @@ -201,6 +201,26 @@ fn test_into_static() {
assert_eq!(a.into_borrowed(), Err(b));
}

#[test]
fn test_as_borrowed() {
let abc: &'static OsStr = OsStr::new("abc");
let medium: &'static OsStr = OsStr::new("abcdefghijklmnopqrstuvwxyz");

// borrowed
let a = H::borrowed(abc);
let b = a.as_borrowed().unwrap();
assert_eq!(b, abc);
assert!(core::ptr::eq(b, abc));

// inline
let a = H::from(abc);
assert_eq!(a.as_borrowed(), None);

// heap
let a = H::from(medium);
assert_eq!(a.as_borrowed(), None);
}

#[test]
fn test_into_bytes() {
let s = HipOsStr::from("A".repeat(42));
Expand Down
29 changes: 29 additions & 0 deletions src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,35 @@ where
self.0.into_borrowed().map(Path::new).map_err(Self)
}

/// Returns the borrowed slice if this `Path` is actually borrowed, `None`
/// otherwise.
///
/// # Examples
///
/// ```
/// # use hipstr::HipPath;
/// # use std::path::Path;
/// let abc: &'static Path = Path::new("abc");
/// let s = HipPath::borrowed(abc);
/// let c: Option<&'static Path> = s.as_borrowed();
/// assert_eq!(c, Some(abc));
/// assert!(std::ptr::eq(abc, c.unwrap()));
///
/// let s2 = HipPath::from(abc);
/// assert!(s2.as_borrowed().is_none());
/// ```
#[inline]
pub const fn as_borrowed(&self) -> Option<&'borrow Path> {
match self.0.as_borrowed() {
Some(slice) => {
// SAFETY: type invariant
// transmute to be "const"
Some(unsafe { core::mem::transmute(slice) })
}
None => None,
}
}

/// Converts a `HipPath` into a `HipOsStr`.
///
/// It consumes the `HipPath` without copying the content
Expand Down
Loading

0 comments on commit 416e20c

Please sign in to comment.