Module dev

Module dev 

Source
Expand description

Everything related to the devices.

§Devices

In this crate, a Device is a structure capable of storing a fixed number of contiguous bytes. Each byte is located at a unique Address, which is used to describe Slices. When a Slice is mutated, it can be committed into a Commit, which can be write back on the Device.

To avoid manipulating only Slices and Commits, which is quite heavy, you can manipulate a Device through the provided metehods read_from_bytes and write_to_bytes.

If needed for the Filesystem usage, the device may be able to give the current time.

§How to implement a device?

§Derived automatically

The easiest way for an object to implement Device is to make it implements the traits Read, Write and Seek from deku::no_std_io or no_std_io2 (which is the same crate re-exported). The advantage of such requirements is that in a std environment, those traits are exactly the ones of std::io, which is helpful not to define twice the same functions.

use std::error::Error;
use std::fmt::Display;

use deku::DekuRead;
use deku::no_std_io::{Read, Seek, SeekFrom, Write};
use efs::dev::Device;
use efs::dev::address::Address;
use efs::fs::file::Base;

struct Foo {} // Foo is our device

impl Read for Foo {
    fn read(&mut self, buf: &mut [u8]) -> deku::no_std_io::Result<usize> {
        buf.fill(1);
        Ok(buf.len())
    }
}

impl Write for Foo {
    fn write(&mut self, buf: &[u8]) -> deku::no_std_io::Result<usize> {
        Ok(buf.len())
    }

    fn flush(&mut self) -> deku::no_std_io::Result<()> {
        Ok(())
    }
}

impl Seek for Foo {
    fn seek(&mut self, _pos: SeekFrom) -> deku::no_std_io::Result<u64> {
        Ok(0)
    }
}

#[derive(Debug, PartialEq, Eq, DekuRead)]
struct Bar {
    a: u8,
    b: u32,
}

let mut foo = Foo {};

// Now `foo` implements `Device,
// thus we can use all the methods from the `Device` trait.

assert_eq!(foo.read_from_bytes::<Bar>(Address::new(0), 5).unwrap(), Bar {
    a: 0x1,
    b: 0x0101_0101
});

Moreover, when using the std feature, the devices derived automatically will use std_now for the implementation of the Device::now method.

§By hand

To implement a device, you need to provide three methods:

  • size which returns the size of the device in bytes

  • slice which creates a Slice of the device

  • commit which commits a Commit created from a mutated Slice of the device

  • now (optional) which returns the current time.

To help you, here is an example of how those methods can be used:

use std::vec;

use efs::dev::address::Address;
use efs::dev::{Device, Wrapper};

// Here, our device is a `Wrapper<Vec<usize>>`
let mut device = Wrapper::new(vec![0_u8; 1024]);

// We take a slice of the device: `slice` now contains a reference to the
// objects between the indices 256 (included) and 512 (not included) of the
// device.
let mut slice = device.slice(Address::from(256_u64)..Address::from(512_u64)).unwrap();

// We modify change each elements `0` to a `1` in the slice.
slice.iter_mut().for_each(|element| *element = 1);

// We commit the changes of slice: now this slice cannot be changed anymore.
let commit = slice.commit();

assert!(device.commit(commit).is_ok());

for (idx, &x) in device.iter().enumerate() {
    assert_eq!(x, u8::from((256..512).contains(&idx)));
}

Moreover, your implementation of a device should only returns deku::no_std_io::Error error in case of a read/write fail.

Modules§

address
General description of addresses in a device.
size
Utilities to manipulate device’s size

Structs§

Commit
Commited slice of a device, filled with objects of type T.
Slice
Slice of a device, filled with objects of type T.
Wrapper
Wrapper structure to be able to use Vec, Box and array as devices.

Traits§

Device
General interface for devices containing a file system.

Functions§

std_nowstd
Returns the current time in the Timespec format.