Skip to main content

InMemoryFs

Struct InMemoryFs 

Source
pub struct InMemoryFs { /* private fields */ }
Expand description

In-memory filesystem implementation.

InMemoryFs is the default filesystem used by Bash::new(). It stores all files and directories in memory using a HashMap, making it ideal for sandboxed execution where no real filesystem access is needed.

§Features

  • Thread-safe: Uses RwLock for concurrent read/write access
  • Binary-safe: Fully supports binary data including null bytes
  • Default directories: Creates /, /tmp, /home, /home/user, /dev
  • Special devices: /dev/null discards writes and returns empty on read

§Example

use bashkit::{Bash, FileSystem, InMemoryFs};
use std::path::Path;
use std::sync::Arc;

// InMemoryFs is the default when using Bash::new()
let mut bash = Bash::new();

// Or create explicitly for direct filesystem access
let fs = Arc::new(InMemoryFs::new());

// Write files
fs.write_file(Path::new("/tmp/test.txt"), b"hello").await?;

// Read files
let content = fs.read_file(Path::new("/tmp/test.txt")).await?;
assert_eq!(content, b"hello");

// Create directories
fs.mkdir(Path::new("/data/nested/dir"), true).await?;

// Check existence
assert!(fs.exists(Path::new("/data/nested/dir")).await?);

// Use with Bash
let mut bash = Bash::builder().fs(fs.clone()).build();
bash.exec("echo 'from bash' >> /tmp/test.txt").await?;

let content = fs.read_file(Path::new("/tmp/test.txt")).await?;
assert_eq!(content, b"hellofrom bash\n");

§Default Directory Structure

InMemoryFs::new() creates these directories:

/
├── tmp/
├── home/
│   └── user/
└── dev/
    └── null  (special device)

§Binary Data

The filesystem fully supports binary data:

use bashkit::{FileSystem, InMemoryFs};
use std::path::Path;

let fs = InMemoryFs::new();

// Write binary with null bytes
let data = vec![0x89, 0x50, 0x4E, 0x47, 0x00, 0xFF];
fs.write_file(Path::new("/tmp/binary.bin"), &data).await?;

// Read it back unchanged
let read = fs.read_file(Path::new("/tmp/binary.bin")).await?;
assert_eq!(read, data);

§Resource Limits

Configure limits to prevent memory exhaustion:

use bashkit::{FileSystem, InMemoryFs, FsLimits};
use std::path::Path;

let limits = FsLimits::new()
    .max_total_bytes(1_000_000)   // 1MB total
    .max_file_size(100_000)       // 100KB per file
    .max_file_count(100);         // 100 files max

let fs = InMemoryFs::with_limits(limits);

// This works
fs.write_file(Path::new("/tmp/small.txt"), b"hello").await?;

// This would fail with "file too large" error:
// let big_data = vec![0u8; 200_000];
// fs.write_file(Path::new("/tmp/big.bin"), &big_data).await?;

Implementations§

Source§

impl InMemoryFs

Source

pub fn new() -> Self

Create a new in-memory filesystem with default directories and default limits.

Creates the following directory structure:

  • / - Root directory
  • /tmp - Temporary files
  • /home - Home directories
  • /home/user - Default user home
  • /dev - Device files
  • /dev/null - Null device (discards writes, returns empty)
§Default Limits
  • Total filesystem: 100MB
  • Single file: 10MB
  • File count: 10,000

Use InMemoryFs::with_limits for custom limits.

§Example
use bashkit::{FileSystem, InMemoryFs};
use std::path::Path;

let fs = InMemoryFs::new();

// Default directories exist
assert!(fs.exists(Path::new("/tmp")).await?);
assert!(fs.exists(Path::new("/home/user")).await?);
assert!(fs.exists(Path::new("/dev/null")).await?);
Source

pub fn with_limits(limits: FsLimits) -> Self

Create a new in-memory filesystem with custom limits.

§Example
use bashkit::{FileSystem, InMemoryFs, FsLimits};
use std::path::Path;

let limits = FsLimits::new()
    .max_total_bytes(50_000_000)  // 50MB
    .max_file_size(5_000_000);    // 5MB per file

let fs = InMemoryFs::with_limits(limits);
Source

pub fn add_file( &self, path: impl AsRef<Path>, content: impl AsRef<[u8]>, mode: u32, )

Add a file with specific mode (synchronous, for initial setup).

This method is primarily used by BashBuilder to pre-populate the filesystem during construction. For runtime file operations, use the async FileSystem::write_file method instead.

Parent directories are created automatically.

§Arguments
  • path - Absolute path where the file will be created
  • content - File content (will be converted to bytes)
  • mode - Unix permission mode (e.g., 0o644 for writable, 0o444 for readonly)
§Example
use bashkit::InMemoryFs;

let fs = InMemoryFs::new();

// Add a writable config file
fs.add_file("/config/app.conf", "debug=true\n", 0o644);

// Add a readonly file
fs.add_file("/etc/version", "1.0.0", 0o444);

Trait Implementations§

Source§

impl Default for InMemoryFs

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl FileSystem for InMemoryFs

Source§

fn read_file<'life0, 'life1, 'async_trait>( &'life0 self, path: &'life1 Path, ) -> Pin<Box<dyn Future<Output = Result<Vec<u8>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Read a file’s contents as bytes. Read more
Source§

fn write_file<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, path: &'life1 Path, content: &'life2 [u8], ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Write contents to a file, creating it if necessary. Read more
Source§

fn append_file<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, path: &'life1 Path, content: &'life2 [u8], ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Append contents to a file, creating it if necessary. Read more
Source§

fn mkdir<'life0, 'life1, 'async_trait>( &'life0 self, path: &'life1 Path, recursive: bool, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Create a directory. Read more
Source§

fn remove<'life0, 'life1, 'async_trait>( &'life0 self, path: &'life1 Path, recursive: bool, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Remove a file or directory. Read more
Source§

fn stat<'life0, 'life1, 'async_trait>( &'life0 self, path: &'life1 Path, ) -> Pin<Box<dyn Future<Output = Result<Metadata>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Get file or directory metadata. Read more
Source§

fn read_dir<'life0, 'life1, 'async_trait>( &'life0 self, path: &'life1 Path, ) -> Pin<Box<dyn Future<Output = Result<Vec<DirEntry>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

List directory contents. Read more
Source§

fn exists<'life0, 'life1, 'async_trait>( &'life0 self, path: &'life1 Path, ) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Check if a path exists. Read more
Source§

fn rename<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, from: &'life1 Path, to: &'life2 Path, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Rename or move a file or directory. Read more
Source§

fn copy<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, from: &'life1 Path, to: &'life2 Path, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Copy a file. Read more
Create a symbolic link. Read more
Read a symbolic link’s target. Read more
Source§

fn chmod<'life0, 'life1, 'async_trait>( &'life0 self, path: &'life1 Path, mode: u32, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Change file permissions. Read more
Source§

fn usage(&self) -> FsUsage

Get current filesystem usage statistics. Read more
Source§

fn limits(&self) -> FsLimits

Get filesystem limits. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.