Skip to main content

AnyChunk

Enum AnyChunk 

Source
pub enum AnyChunk<const BODY_SIZE: usize = DEFAULT_BODY_SIZE> {
    Content(ContentChunk<BODY_SIZE>),
    SingleOwner(SingleOwnerChunk<BODY_SIZE>),
}
Expand description

Type-erased chunk for runtime polymorphism with configurable body size.

This enum provides dynamic dispatch for chunks without requiring object-safe traits. Use this when you need to store heterogeneous chunk types in collections or pass chunks through interfaces that can’t be generic.

§Why an enum instead of Box<dyn Chunk>?

The Chunk trait has an associated type (type Header) which makes it not object-safe. This enum provides the same functionality while maintaining type safety.

§Examples

use nectar_primitives::{AnyChunk, Chunk, ContentChunk, ChunkTypeId};

// Create a content chunk
let content = ContentChunk::new(&b"hello world"[..]).unwrap();
let any: AnyChunk = content.clone().into();

// Access common properties
assert_eq!(any.type_id(), ChunkTypeId::CONTENT);

// Get the concrete type back
if let Some(recovered) = any.as_content() {
    assert_eq!(recovered.address(), content.address());
}

Variants§

§

Content(ContentChunk<BODY_SIZE>)

A content-addressed chunk (CAC).

§

SingleOwner(SingleOwnerChunk<BODY_SIZE>)

A single-owner chunk (SOC).

Implementations§

Source§

impl<const BODY_SIZE: usize> AnyChunk<BODY_SIZE>

Source

pub fn address(&self) -> &ChunkAddress

Get the address of this chunk.

Source

pub fn data(&self) -> &Bytes

Get the raw data contained in this chunk.

Source

pub const fn type_id(&self) -> ChunkTypeId

Get the type ID of this chunk.

Source

pub fn size(&self) -> usize

Get the total size of this chunk in bytes.

Source

pub fn span(&self) -> u64

Get the span (logical data length) of this chunk: the BMT span of its underlying body.

Source

pub fn transformed_address(&self, anchor: &[u8]) -> ChunkAddress

Compute the anchor-keyed transformed address of this chunk.

The transformed address is the redistribution sampler’s per-round, per-node re-hash of a chunk. It is a prefixed BMT root keyed by the node’s anchor, used to order reserve chunks deterministically while binding the ordering to the proving node. This reproduces bee’s storer.transformedAddress (pkg/storer/sample.go) byte-for-byte.

§Derivation
  • For a content-addressed chunk (CAC) the transformed address is the prefixed BMT of the chunk body, i.e. BMT(prefix = anchor, span, payload). This is computed by BmtBody::transformed_root on the chunk’s borrowed body, which mixes the anchor into every node hash, matching bee’s prefix hasher.
  • For a single-owner chunk (SOC) the wrapped content body is re-hashed the same way to obtain inner, then the SOC’s transformed address is a plain, unprefixed keccak256(soc_address || inner). The outer wrap is a flat Keccak256, not a prefixed BMT, mirroring bee’s transformedAddressSOC which uses swarm.NewHasher() (no anchor) for the final combine.
§Endianness

The span is serialised little-endian inside the BMT. Do not confuse this with the big-endian encodings used elsewhere on the redistribution wire (e.g. proof witness indices); the BMT span is always LE.

§Borrowing

The CAC and SOC paths dispatch through borrowed body accessors (ContentChunk::body and SingleOwnerChunk::inner_body), so no chunk or body is cloned. For a SOC the wrapped body already is the content chunk’s span || payload, so the inner root needs no 32 + 65 (id + signature) header slicing.

Source

pub fn verify(&self, expected: &ChunkAddress) -> Result<()>

Verify that this chunk’s address matches an expected address.

Source

pub fn into_bytes(self) -> Bytes

Convert this chunk into its serialized bytes representation.

Source

pub fn is<T: ChunkType>(&self) -> bool

Check if this chunk is of a specific type.

Source

pub const fn is_content(&self) -> bool

Check if this is a content chunk.

Source

pub const fn is_single_owner(&self) -> bool

Check if this is a single-owner chunk.

Source

pub const fn as_content(&self) -> Option<&ContentChunk<BODY_SIZE>>

Get a reference to the contained ContentChunk, if this is one.

Source

pub const fn as_single_owner(&self) -> Option<&SingleOwnerChunk<BODY_SIZE>>

Get a reference to the contained SingleOwnerChunk, if this is one.

Source

pub fn into_content(self) -> Option<ContentChunk<BODY_SIZE>>

Convert into the contained ContentChunk, if this is one.

Source

pub fn into_single_owner(self) -> Option<SingleOwnerChunk<BODY_SIZE>>

Convert into the contained SingleOwnerChunk, if this is one.

Source

pub fn to_typed_bytes(&self) -> Vec<u8>

Encode this chunk as a type-tagged, self-describing byte string.

The layout is [type_id: 1 byte][chunk wire bytes], where the chunk wire bytes are the same form produced by AnyChunk::into_bytes (the inverse of ContentChunk::try_from/SingleOwnerChunk::try_from).

The chunk address is deliberately not embedded. It is supplied from context on decode (for example the redb key when reading from storage, or the address field of a wire message). This mirrors the existing reconstruction paths that take an expected address.

Unlike the address-disambiguating reconstruction path, decoding the result of this method dispatches purely by type_id, so it never has to trial-parse both the content and single-owner shapes.

§Examples
use nectar_primitives::{AnyChunk, Chunk, ContentChunk};

let content = ContentChunk::new(&b"hello world"[..]).unwrap();
let address = *content.address();
let any: AnyChunk = content.into();

let encoded = any.to_typed_bytes();
assert_eq!(encoded[0], 0); // CONTENT type id

let decoded: AnyChunk = AnyChunk::from_typed_bytes(&address, &encoded).unwrap();
assert_eq!(decoded.address(), any.address());
Source

pub fn from_typed_bytes(address: &ChunkAddress, bytes: &[u8]) -> Result<Self>

Decode a type-tagged chunk produced by AnyChunk::to_typed_bytes.

The leading byte selects the chunk type and the remainder is the chunk wire payload. address is the expected chunk address (for example the redb storage key or the wire message address field); the decoded chunk is verified against it.

Decoding dispatches by the type tag and therefore never trial-parses the other chunk shape. Only the standard content and single-owner types are recognised; any other tag is an error (custom chunk types are tracked separately as a future registration mechanism).

§Errors

Returns an error (and never panics) when:

  • the input is empty (no type tag),
  • the type tag is not a recognised standard chunk type,
  • the payload cannot be decoded as the tagged chunk type, or
  • a standard chunk’s computed address does not match address.
Source

pub fn from_wire_bytes(address: &ChunkAddress, data: Bytes) -> Result<Self>

Decode a chunk from its bare wire bytes (NO type tag) given the expected address, disambiguating content vs single-owner by which one hashes to address. This is the type-less wire form (e.g. a Delivery data field); prefer from_typed_bytes for self-describing storage. Only content and single-owner shapes are recognised; bytes that parse as neither (for the given address) error.

Reconstructing an AnyChunk from raw bytes is ambiguous without the address: a ContentChunk parse almost always succeeds structurally (a span plus an arbitrary payload), so the expected address is the disambiguator. The chunk is whichever variant parses and hashes to address. Content is tried first, then single-owner; a lying address makes both attempts fail, so the address is self-validating against the bytes.

§Errors

Returns a verification error (and never panics) when neither the content nor the single-owner interpretation of data hashes to address.

Trait Implementations§

Source§

impl<const BODY_SIZE: usize> Clone for AnyChunk<BODY_SIZE>

Source§

fn clone(&self) -> AnyChunk<BODY_SIZE>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<const BODY_SIZE: usize> Debug for AnyChunk<BODY_SIZE>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<const BODY_SIZE: usize> Eq for AnyChunk<BODY_SIZE>

Source§

impl<const BODY_SIZE: usize> From<ContentChunk<BODY_SIZE>> for AnyChunk<BODY_SIZE>

Source§

fn from(chunk: ContentChunk<BODY_SIZE>) -> Self

Converts to this type from the input type.
Source§

impl<const BODY_SIZE: usize> From<SingleOwnerChunk<BODY_SIZE>> for AnyChunk<BODY_SIZE>

Source§

fn from(chunk: SingleOwnerChunk<BODY_SIZE>) -> Self

Converts to this type from the input type.
Source§

impl<const BODY_SIZE: usize> PartialEq for AnyChunk<BODY_SIZE>

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Auto Trait Implementations§

§

impl<const BODY_SIZE: usize = DEFAULT_BODY_SIZE> !Freeze for AnyChunk<BODY_SIZE>

§

impl<const BODY_SIZE: usize> RefUnwindSafe for AnyChunk<BODY_SIZE>

§

impl<const BODY_SIZE: usize> Send for AnyChunk<BODY_SIZE>

§

impl<const BODY_SIZE: usize> Sync for AnyChunk<BODY_SIZE>

§

impl<const BODY_SIZE: usize> Unpin for AnyChunk<BODY_SIZE>

§

impl<const BODY_SIZE: usize> UnsafeUnpin for AnyChunk<BODY_SIZE>

§

impl<const BODY_SIZE: usize> UnwindSafe for AnyChunk<BODY_SIZE>

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> MaybeSend for T
where T: Send + ?Sized,

Source§

impl<T> MaybeSync for T
where T: Sync + ?Sized,

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more