summaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-07-02 19:59:52 +0200
committerLaurenz <laurmaedje@gmail.com>2023-07-02 20:07:43 +0200
commitebfdb1dafa430786db10dad2ef7d5467c1bdbed1 (patch)
tree2bbc24ddb4124c4bb14dec0e536129d4de37b056 /src/util
parent3ab19185093d7709f824b95b979060ce125389d8 (diff)
Move everything into `crates/` directory
Diffstat (limited to 'src/util')
-rw-r--r--src/util/bytes.rs59
-rw-r--r--src/util/fat.rs55
-rw-r--r--src/util/mod.rs268
3 files changed, 0 insertions, 382 deletions
diff --git a/src/util/bytes.rs b/src/util/bytes.rs
deleted file mode 100644
index 9165467b..00000000
--- a/src/util/bytes.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-use std::borrow::Cow;
-use std::fmt::{self, Debug, Formatter};
-use std::ops::Deref;
-use std::sync::Arc;
-
-use comemo::Prehashed;
-
-/// A shared byte buffer that is cheap to clone and hash.
-#[derive(Clone, Hash, Eq, PartialEq)]
-pub struct Bytes(Arc<Prehashed<Cow<'static, [u8]>>>);
-
-impl Bytes {
- /// Create a buffer from a static byte slice.
- pub fn from_static(slice: &'static [u8]) -> Self {
- Self(Arc::new(Prehashed::new(Cow::Borrowed(slice))))
- }
-
- /// Return a view into the buffer.
- pub fn as_slice(&self) -> &[u8] {
- self
- }
-
- /// Return a copy of the buffer as a vector.
- pub fn to_vec(&self) -> Vec<u8> {
- self.0.to_vec()
- }
-}
-
-impl From<&[u8]> for Bytes {
- fn from(slice: &[u8]) -> Self {
- Self(Arc::new(Prehashed::new(slice.to_vec().into())))
- }
-}
-
-impl From<Vec<u8>> for Bytes {
- fn from(vec: Vec<u8>) -> Self {
- Self(Arc::new(Prehashed::new(vec.into())))
- }
-}
-
-impl Deref for Bytes {
- type Target = [u8];
-
- fn deref(&self) -> &Self::Target {
- &self.0
- }
-}
-
-impl AsRef<[u8]> for Bytes {
- fn as_ref(&self) -> &[u8] {
- self
- }
-}
-
-impl Debug for Bytes {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "bytes({})", self.len())
- }
-}
diff --git a/src/util/fat.rs b/src/util/fat.rs
deleted file mode 100644
index d3c9bb20..00000000
--- a/src/util/fat.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-//! Fat pointer handling.
-//!
-//! This assumes the memory representation of fat pointers. Although it is not
-//! guaranteed by Rust, it's improbable that it will change. Still, when the
-//! pointer metadata APIs are stable, we should definitely move to them:
-//! <https://github.com/rust-lang/rust/issues/81513>
-
-use std::alloc::Layout;
-use std::mem;
-
-/// Create a fat pointer from a data address and a vtable address.
-///
-/// # Safety
-/// Must only be called when `T` is a `dyn Trait`. The data address must point
-/// to a value whose type implements the trait of `T` and the `vtable` must have
-/// been extracted with [`vtable`].
-#[track_caller]
-pub unsafe fn from_raw_parts<T: ?Sized>(data: *const (), vtable: *const ()) -> *const T {
- let fat = FatPointer { data, vtable };
- debug_assert_eq!(Layout::new::<*const T>(), Layout::new::<FatPointer>());
- mem::transmute_copy::<FatPointer, *const T>(&fat)
-}
-
-/// Create a mutable fat pointer from a data address and a vtable address.
-///
-/// # Safety
-/// Must only be called when `T` is a `dyn Trait`. The data address must point
-/// to a value whose type implements the trait of `T` and the `vtable` must have
-/// been extracted with [`vtable`].
-#[track_caller]
-pub unsafe fn from_raw_parts_mut<T: ?Sized>(data: *mut (), vtable: *const ()) -> *mut T {
- let fat = FatPointer { data, vtable };
- debug_assert_eq!(Layout::new::<*mut T>(), Layout::new::<FatPointer>());
- mem::transmute_copy::<FatPointer, *mut T>(&fat)
-}
-
-/// Extract the address to a trait object's vtable.
-///
-/// # Safety
-/// Must only be called when `T` is a `dyn Trait`.
-#[track_caller]
-pub unsafe fn vtable<T: ?Sized>(ptr: *const T) -> *const () {
- debug_assert_eq!(Layout::new::<*const T>(), Layout::new::<FatPointer>());
- mem::transmute_copy::<*const T, FatPointer>(&ptr).vtable
-}
-
-/// The memory representation of a trait object pointer.
-///
-/// Although this is not guaranteed by Rust, it's improbable that it will
-/// change.
-#[repr(C)]
-struct FatPointer {
- data: *const (),
- vtable: *const (),
-}
diff --git a/src/util/mod.rs b/src/util/mod.rs
deleted file mode 100644
index 05914b04..00000000
--- a/src/util/mod.rs
+++ /dev/null
@@ -1,268 +0,0 @@
-//! Utilities.
-
-pub mod fat;
-
-mod bytes;
-
-pub use bytes::Bytes;
-
-use std::fmt::{self, Debug, Formatter};
-use std::hash::Hash;
-use std::num::NonZeroUsize;
-use std::path::{Component, Path, PathBuf};
-use std::sync::Arc;
-
-use siphasher::sip128::{Hasher128, SipHasher13};
-
-/// Turn a closure into a struct implementing [`Debug`].
-pub fn debug<F>(f: F) -> impl Debug
-where
- F: Fn(&mut Formatter) -> fmt::Result,
-{
- struct Wrapper<F>(F);
-
- impl<F> Debug for Wrapper<F>
- where
- F: Fn(&mut Formatter) -> fmt::Result,
- {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- self.0(f)
- }
- }
-
- Wrapper(f)
-}
-
-/// Calculate a 128-bit siphash of a value.
-pub fn hash128<T: Hash + ?Sized>(value: &T) -> u128 {
- let mut state = SipHasher13::new();
- value.hash(&mut state);
- state.finish128().as_u128()
-}
-
-/// An extra constant for [`NonZeroUsize`].
-pub trait NonZeroExt {
- /// The number `1`.
- const ONE: Self;
-}
-
-impl NonZeroExt for NonZeroUsize {
- const ONE: Self = match Self::new(1) {
- Some(v) => v,
- None => unreachable!(),
- };
-}
-
-/// Extra methods for [`str`].
-pub trait StrExt {
- /// The number of code units this string would use if it was encoded in
- /// UTF16. This runs in linear time.
- fn len_utf16(&self) -> usize;
-}
-
-impl StrExt for str {
- fn len_utf16(&self) -> usize {
- self.chars().map(char::len_utf16).sum()
- }
-}
-
-/// Extra methods for [`Arc`].
-pub trait ArcExt<T> {
- /// Takes the inner value if there is exactly one strong reference and
- /// clones it otherwise.
- fn take(self) -> T;
-}
-
-impl<T: Clone> ArcExt<T> for Arc<T> {
- fn take(self) -> T {
- match Arc::try_unwrap(self) {
- Ok(v) => v,
- Err(rc) => (*rc).clone(),
- }
- }
-}
-
-/// Extra methods for [`[T]`](slice).
-pub trait SliceExt<T> {
- /// Split a slice into consecutive runs with the same key and yield for
- /// each such run the key and the slice of elements with that key.
- fn group_by_key<K, F>(&self, f: F) -> GroupByKey<'_, T, F>
- where
- F: FnMut(&T) -> K,
- K: PartialEq;
-}
-
-impl<T> SliceExt<T> for [T] {
- fn group_by_key<K, F>(&self, f: F) -> GroupByKey<'_, T, F> {
- GroupByKey { slice: self, f }
- }
-}
-
-/// This struct is created by [`SliceExt::group_by_key`].
-pub struct GroupByKey<'a, T, F> {
- slice: &'a [T],
- f: F,
-}
-
-impl<'a, T, K, F> Iterator for GroupByKey<'a, T, F>
-where
- F: FnMut(&T) -> K,
- K: PartialEq,
-{
- type Item = (K, &'a [T]);
-
- fn next(&mut self) -> Option<Self::Item> {
- let mut iter = self.slice.iter();
- let key = (self.f)(iter.next()?);
- let count = 1 + iter.take_while(|t| (self.f)(t) == key).count();
- let (head, tail) = self.slice.split_at(count);
- self.slice = tail;
- Some((key, head))
- }
-}
-
-/// Extra methods for [`Path`].
-pub trait PathExt {
- /// Lexically normalize a path.
- fn normalize(&self) -> PathBuf;
-
- /// Treat `self` as a virtual root relative to which the `path` is resolved.
- ///
- /// Returns `None` if the path lexically escapes the root. The path
- /// might still escape through symlinks.
- fn join_rooted(&self, path: &Path) -> Option<PathBuf>;
-}
-
-impl PathExt for Path {
- fn normalize(&self) -> PathBuf {
- let mut out = PathBuf::new();
- for component in self.components() {
- match component {
- Component::CurDir => {}
- Component::ParentDir => match out.components().next_back() {
- Some(Component::Normal(_)) => {
- out.pop();
- }
- _ => out.push(component),
- },
- Component::Prefix(_) | Component::RootDir | Component::Normal(_) => {
- out.push(component)
- }
- }
- }
- if out.as_os_str().is_empty() {
- out.push(Component::CurDir);
- }
- out
- }
-
- fn join_rooted(&self, path: &Path) -> Option<PathBuf> {
- let mut parts: Vec<_> = self.components().collect();
- let root = parts.len();
- for component in path.components() {
- match component {
- Component::Prefix(_) => return None,
- Component::RootDir => parts.truncate(root),
- Component::CurDir => {}
- Component::ParentDir => {
- if parts.len() <= root {
- return None;
- }
- parts.pop();
- }
- Component::Normal(_) => parts.push(component),
- }
- }
- if parts.len() < root {
- return None;
- }
- Some(parts.into_iter().collect())
- }
-}
-
-/// Format pieces separated with commas and a final "and" or "or".
-pub fn separated_list(pieces: &[impl AsRef<str>], last: &str) -> String {
- let mut buf = String::new();
- for (i, part) in pieces.iter().enumerate() {
- match i {
- 0 => {}
- 1 if pieces.len() == 2 => {
- buf.push(' ');
- buf.push_str(last);
- buf.push(' ');
- }
- i if i + 1 == pieces.len() => {
- buf.push_str(", ");
- buf.push_str(last);
- buf.push(' ');
- }
- _ => buf.push_str(", "),
- }
- buf.push_str(part.as_ref());
- }
- buf
-}
-
-/// Format a comma-separated list.
-///
-/// Tries to format horizontally, but falls back to vertical formatting if the
-/// pieces are too long.
-pub fn pretty_comma_list(pieces: &[impl AsRef<str>], trailing_comma: bool) -> String {
- const MAX_WIDTH: usize = 50;
-
- let mut buf = String::new();
- let len = pieces.iter().map(|s| s.as_ref().len()).sum::<usize>()
- + 2 * pieces.len().saturating_sub(1);
-
- if len <= MAX_WIDTH {
- for (i, piece) in pieces.iter().enumerate() {
- if i > 0 {
- buf.push_str(", ");
- }
- buf.push_str(piece.as_ref());
- }
- if trailing_comma {
- buf.push(',');
- }
- } else {
- for piece in pieces {
- buf.push_str(piece.as_ref().trim());
- buf.push_str(",\n");
- }
- }
-
- buf
-}
-
-/// Format an array-like construct.
-///
-/// Tries to format horizontally, but falls back to vertical formatting if the
-/// pieces are too long.
-pub fn pretty_array_like(parts: &[impl AsRef<str>], trailing_comma: bool) -> String {
- let list = pretty_comma_list(parts, trailing_comma);
- let mut buf = String::new();
- buf.push('(');
- if list.contains('\n') {
- buf.push('\n');
- for (i, line) in list.lines().enumerate() {
- if i > 0 {
- buf.push('\n');
- }
- buf.push_str(" ");
- buf.push_str(line);
- }
- buf.push('\n');
- } else {
- buf.push_str(&list);
- }
- buf.push(')');
- buf
-}
-
-/// Check if the [`Option`]-wrapped L is same to R.
-pub fn option_eq<L, R>(left: Option<L>, other: R) -> bool
-where
- L: PartialEq<R>,
-{
- left.map(|v| v == other).unwrap_or(false)
-}