#file-path #random-data #auto-impl #per-for-system #system-random

sys_traits

Trait per function for system related functionality

31 releases

new 0.1.24 Feb 5, 2026
0.1.22 Jan 15, 2026
0.1.21 Dec 7, 2025
0.1.19 Nov 5, 2025
0.1.6 Dec 31, 2024

#65 in Filesystem

Download history 12080/week @ 2025-10-16 12645/week @ 2025-10-23 12437/week @ 2025-10-30 11010/week @ 2025-11-06 11741/week @ 2025-11-13 22392/week @ 2025-11-20 33510/week @ 2025-11-27 40514/week @ 2025-12-04 50236/week @ 2025-12-11 44088/week @ 2025-12-18 23214/week @ 2025-12-25 33315/week @ 2026-01-01 27905/week @ 2026-01-08 18547/week @ 2026-01-15 21464/week @ 2026-01-22 24256/week @ 2026-01-29

99,836 downloads per month
Used in 93 crates (27 directly)

MIT license

205KB
6.5K SLoC

sys_traits

Trait per function for system related functionality.

Write functions that specify only the system functions they need.

use sys_traits::FsWriteFile;
use sys_traits::SystemRandom;

pub fn write_random_data<TSys: FsWriteFile + SystemRandom>(
  sys: &TSys,
  file_path: &Path,
) -> std::io::Result<()> {
  let mut buf = [0u8; 16];
  sys.sys_random(&mut buf)?;
  sys.fs_write_file(file_path, buf)
}

Now a caller only needs to provide a type that implements those two functions.

#[sys_traits::auto_impl]

Use the #[sys_traits::auto_impl] macro to reduce boilerplate when wanting to automatically implement a trait for T when T implements the required traits.

This is useful for aliasing and reducing verbosity when using this crate.

+#[sys_traits::auto_impl]
pub trait WriteRandomDataSys: FsWriteFile + SystemRandom
{
}

-impl<T> DenoResolverSys for T where T: FsWriteFile + SystemRandom
-{
-}

Implementations

Comes with two implementations that implement all the traits.

  • sys_traits::impl::RealSys - A real implementation of the current system.
  • sys_traits::impl::InMemorySys - An in-memory system useful for testing.

Creating an implementation

To create an implementation you must implement the traits; however, some traits require implementing Base<TraitName> traits instead. For example, instead of implementing FsWrite, you must implement BaseFsWrite:

pub struct MyCustomFileSystem;

impl sys_traits::BaseFsWrite for MyCustomFileSystem {
  fn base_fs_write(&self, path: &Path, data: &[u8]) -> std::io::Result<()> {
    // ...
  }
}

The sys_traits::FsWrite trait gets automatically implemented for this as its definition is:

pub trait FsWrite: BaseFsWrite {
  #[inline]
  fn fs_write(
    &self,
    path: impl AsRef<Path>,
    data: impl AsRef<[u8]>,
  ) -> std::io::Result<()> {
    self.base_fs_write(path.as_ref(), data.as_ref())
  }
}

impl<T: BaseFsWrite> FsWrite for T {}

There's two reasons for this:

  1. You can't box traits with impl ....
  2. By design it limits code generation of multiple kinds of impl AsRef<Path> and impl AsRef<[u8]> to only being a single statement.

Error Context

By default, filesystem errors don't include path information:

No such file or directory (os error 2)

Use .with_paths_in_errors() to wrap operations with context that includes the operation name and path:

use sys_traits::PathsInErrorsExt;
use sys_traits::impls::RealSys;

let sys = RealSys;

// returns: "failed to read '/path/to/file': No such file or directory (os error 2)"
sys.with_paths_in_errors().fs_read("/path/to/file")?;

The returned io::Error preserves the original error kind and can be downcast to OperationError for programmatic access:

use sys_traits::OperationError;
use sys_traits::OperationErrorKind;

let err = sys.with_paths_in_errors().fs_read("/nonexistent").unwrap_err();

// error kind is preserved
assert_eq!(err.kind(), std::io::ErrorKind::NotFound);

// downcast for programmatic access
if let Some(op_err) = err.get_ref().and_then(|e| e.downcast_ref::<OperationError>()) {
  assert_eq!(op_err.operation(), "read");
  assert_eq!(op_err.kind(), &OperationErrorKind::WithPath("/nonexistent".to_string()));
}

Dependencies

~0.1–12MB
~82K SLoC