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>
impl<'a> Defragmenter<'a>
Sourcepub const fn matrix_len(nb_frag: u16, max_lost: u16) -> usize
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);Sourcepub fn new(
nb_frag: u16,
frag_size: u8,
block: &'a mut [u8],
matrix: &'a mut [u8],
) -> Result<Defragmenter<'a>, FragError>
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_sizebytes.matrix- the working storage, whose size decides how many losses can be solved for;Defragmenter::matrix_lensizes 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.
Sourcepub fn resumed(
nb_frag: u16,
frag_size: u8,
block: &'a mut [u8],
matrix: &'a mut [u8],
progress: Progress,
) -> Result<Defragmenter<'a>, FragError>
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- whatDefragmenter::progressreported.
§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);Sourcepub const fn progress(&self) -> Progress
pub const fn progress(&self) -> Progress
How far the session has got, to be kept beside its storage.
§Returns
The numbers Defragmenter::resumed takes.
Sourcepub fn block(&self) -> &[u8] ⓘ
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.
Sourcepub const fn done(&self) -> bool
pub const fn done(&self) -> bool
Whether the whole block is there.
§Returns
true once every uncoded fragment has arrived or been solved for.
Sourcepub const fn received(&self) -> u16
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.
Sourcepub const fn missing(&self) -> u16
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.
Sourcepub const fn max_lost(&self) -> u16
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.
Sourcepub fn fragment(&mut self, n: u16, data: &[u8]) -> Result<bool, FragError>
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_sizeof 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.