Skip to main content

Defragmenter

Struct Defragmenter 

Source
pub struct Defragmenter<'a> { /* private fields */ }
Expand description

Puts a data block back together from the fragments that arrive, TS004-2.0.0 appendix A.2.

The uncoded fragments go straight into the caller’s block storage. A coded fragment is reduced against everything already known and, if it still says something new, kept as one row of a triangular system over the fragments that were lost. Once there are as many rows as there are losses, the system is solved back into the block.

Nothing is allocated. The block storage is nb_frag * frag_size bytes, and the matrix storage bounds how many losses can be solved for: Defragmenter::matrix_len says how much room a given number of losses takes.

Implementations§

Source§

impl<'a> Defragmenter<'a>

Source

pub const fn matrix_len(nb_frag: u16, max_lost: u16) -> usize

How many bytes of matrix storage a session needs.

§Arguments
  • nb_frag - how many uncoded fragments the block was cut into.
  • max_lost - the most uncoded fragments the session should survive losing.
§Returns

The byte count: a row for each loss, as wide as the losses; the map from row to fragment; and a bit for each uncoded fragment saying whether it is in hand.

§Examples
use pamoja_lorawan::packages::fragment::Defragmenter;

assert_eq!(Defragmenter::matrix_len(100, 8), 8 + 2 * 8 + 13);
Source

pub fn new( nb_frag: u16, frag_size: u8, block: &'a mut [u8], matrix: &'a mut [u8], ) -> Result<Defragmenter<'a>, FragError>

Starts a session.

§Arguments
  • nb_frag - how many uncoded fragments the block was cut into.
  • frag_size - how many bytes each fragment carries.
  • block - where the block is put back together, nb_frag * frag_size bytes.
  • matrix - the working storage, whose size decides how many losses can be solved for; Defragmenter::matrix_len sizes it.
§Returns

The session, with nothing received.

§Errors

FragError::Session for a session this build does not run, and FragError::Storage when the block storage is too small.

Source

pub fn resumed( nb_frag: u16, frag_size: u8, block: &'a mut [u8], matrix: &'a mut [u8], progress: Progress, ) -> Result<Defragmenter<'a>, FragError>

Starts a session again where one left off.

The storage must be the same two buffers the earlier session held, with whatever they had in them, and the progress must be the one it reported. Nothing is cleared.

§Arguments
  • nb_frag - how many uncoded fragments the block was cut into.
  • frag_size - how many bytes each fragment carries.
  • block - the block storage, as the earlier session left it.
  • matrix - the working storage, as the earlier session left it.
  • progress - what Defragmenter::progress reported.
§Returns

The session, carrying on.

§Errors

FragError::Session for a session this build does not run, and FragError::Storage when the storage is too small.

§Examples
use pamoja_lorawan::packages::fragment::{Defragmenter, Fragmenter};

let block = b"a block that outlives the power";
let sender = Fragmenter::new(block, 8)?;
let mut store = [0u8; 32];
let mut matrix = [0u8; 64];

let mut piece = [0u8; 8];
let mut session = Defragmenter::new(sender.nb_frag(), 8, &mut store, &mut matrix)?;
sender.fragment(1, &mut piece)?;
session.fragment(1, &piece)?;
let progress = session.progress();

// The power goes. The two buffers were in flash; this is all that was beside them.
let mut session =
    Defragmenter::resumed(sender.nb_frag(), 8, &mut store, &mut matrix, progress)?;
for n in 2..=sender.nb_frag() {
    sender.fragment(n, &mut piece)?;
    session.fragment(n, &piece)?;
}
assert!(session.done());
assert_eq!(&session.block()[..block.len()], block);
Source

pub const fn progress(&self) -> Progress

How far the session has got, to be kept beside its storage.

§Returns

The numbers Defragmenter::resumed takes.

Source

pub fn block(&self) -> &[u8] ⓘ

The block, as far as it has been put back together.

§Returns

The bytes, which are the whole block once Defragmenter::done is true, padding and all. The padding the session setup named is at the end.

Source

pub const fn done(&self) -> bool

Whether the whole block is there.

§Returns

true once every uncoded fragment has arrived or been solved for.

Source

pub const fn received(&self) -> u16

How many fragments arrived, coded and uncoded, including repeats.

§Returns

The count, which a status answer reports as NbFragReceived.

Source

pub const fn missing(&self) -> u16

How many uncoded fragments are still missing.

§Returns

The count, which is also the least number of further independent fragments needed. A status answer reports it as MissingFrag, capped at 255.

Source

pub const fn max_lost(&self) -> u16

How many losses this session can still solve for.

§Returns

The count the caller’s matrix storage allows.

Source

pub fn fragment(&mut self, n: u16, data: &[u8]) -> Result<bool, FragError>

Takes one fragment of the session.

§Arguments
  • n - which fragment, counting from one.
  • data - its bytes, frag_size of them.
§Returns

Whether the block is now complete.

§Errors

FragError::Fragment for a fragment outside the session or of the wrong size, and FragError::Memory when more uncoded fragments were lost than there is room to solve for.

Auto Trait Implementations§

§

impl<'a> !UnwindSafe for Defragmenter<'a>

§

impl<'a> Freeze for Defragmenter<'a>

§

impl<'a> RefUnwindSafe for Defragmenter<'a>

§

impl<'a> Send for Defragmenter<'a>

§

impl<'a> Sync for Defragmenter<'a>

§

impl<'a> Unpin for Defragmenter<'a>

§

impl<'a> UnsafeUnpin for Defragmenter<'a>

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> Same for T

Source§

type Output = T

Should always be Self
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.