Skip to main content

FileWriter

Struct FileWriter 

Source
pub struct FileWriter<W> { /* private fields */ }
Expand description

Writes a Hurray file in a single forward pass without seeks.

The file format is:

[ File header      ]  64 bytes
[ Tensor 0         ]  descriptor + padding + data buffers
[ Tensor 1         ]
  ...
[ KV section       ]  optional, written by finish()
[ Footer index     ]  written by finish()
[ Trailer          ]  40 bytes, written by finish()

This is a driver, not an encoder: FileWriterCore holds the container format, the offsets and the growing index, and this type only writes the bytes the core offers and reports how many the sink took (ADR-041 § 7).

HAS_KV_METADATA is not set in the header because KV content is supplied to finish, after the header has already gone out, and this writer never seeks back. Readers treat a non-zero trailer kv_offset as authoritative.

§Examples

use hurray_core::{
    BufferHandle, DeviceTag, ElementType, LayoutDescriptor, Shape, SyncMode,
    TensorDescriptor, MIN_BUFFER_ALIGNMENT,
};
use hurray_io::file::{FileWriter, KvValue};

let handle = BufferHandle::new(
    16, MIN_BUFFER_ALIGNMENT, DeviceTag::Cpu, SyncMode::ProducerSynced,
)?;
let descriptor = TensorDescriptor::new(
    1, 0, ElementType::Float32, Shape::new(vec![2u64, 2])?, 0,
    LayoutDescriptor::RowMajor, vec![handle], None, None, None, None,
)?;
let data = [0u8; 16];

let file = tokio::fs::File::create("model.hrry").await?;
let mut writer = FileWriter::new(file).await?;
writer.write_tensor("weight", &descriptor, &[&data]).await?;
writer
    .finish(vec![("producer".into(), KvValue::String("hurray".into()))])
    .await?;

Implementations§

Source§

impl<W: AsyncWrite + Unpin> FileWriter<W>

Source

pub async fn new(inner: W) -> Result<Self>

Creates a writer with default options (4096-byte buffer alignment, unsorted index).

Source

pub async fn with_options(inner: W, options: FileWriterOptions) -> Result<Self>

Creates a writer with custom options.

§Errors
Source

pub async fn write_tensor( &mut self, name: &str, desc: &TensorDescriptor, buffers: &[&[u8]], ) -> Result<()>

Encodes and writes one tensor.

§Errors
Source

pub async fn write_composite( &mut self, head_name: &str, head: &TensorDescriptor, members: &[FileCompositeNode<'_>], ) -> Result<()>

Writes a composite tensor: its head, then every member’s descriptor and data, contiguously and in order (ADR-027 § Binding).

Every tensor — the head and each member — gets its own footer-index entry, so all are individually addressable by name via read_tensor. Membership is recoverable by read_composite from the head’s member_count plus file-offset adjacency (the members are the tensors written immediately after the head). Nested composites are written in the same pass.

The whole group is validated up front — reusing CompositeValidator for member count and per-rule constraints (partition exact-cover, overlay ordering) — before any tensor is written.

§Errors
  • Error::Core — the head is not a valid composite head, or validation failed
  • the name/buffer errors of write_tensor for the head or any member
  • Error::Io — underlying write error
§Examples
use hurray_core::{
    layout::{CompositeLayout, CompositionRule, LayoutDescriptor},
    ElementType, Shape, TensorDescriptor,
};
use hurray_io::file::{FileCompositeNode, FileWriter};

let head = TensorDescriptor::new(
    1, 0, ElementType::Float32, Shape::new(vec![8u64, 8]).unwrap(), 0,
    LayoutDescriptor::Composite(CompositeLayout::new(CompositionRule::Partition, 2).unwrap()),
    vec![], None, None, None, None,
)?;
let file = tokio::fs::File::create("model.hrry").await?;
let mut writer = FileWriter::new(file).await?;
writer.write_composite("weight", &head, &members).await?;
writer.finish(vec![]).await?;
Source

pub async fn finish(self, kv: Vec<(String, KvValue)>) -> Result<W>

Writes the KV section, footer index, and trailer, then flushes.

kv is a list of (key, value) pairs. Keys must be non-empty, at most 65 535 bytes, and unique within the list.

§Errors

Auto Trait Implementations§

§

impl<W> Freeze for FileWriter<W>
where W: Freeze,

§

impl<W> RefUnwindSafe for FileWriter<W>
where W: RefUnwindSafe,

§

impl<W> Send for FileWriter<W>
where W: Send,

§

impl<W> Sync for FileWriter<W>
where W: Sync,

§

impl<W> Unpin for FileWriter<W>
where W: Unpin,

§

impl<W> UnsafeUnpin for FileWriter<W>
where W: UnsafeUnpin,

§

impl<W> UnwindSafe for FileWriter<W>
where W: UnwindSafe,

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.