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 region    ]  descriptor → pad → buffers → pad  (repeated)
[ KV section       ]  optional, written by finish()
[ Index section    ]  written by finish()
[ Trailer          ]  40 bytes

§Note on HAS_KV_METADATA

This writer sets HAS_KV_METADATA = 0 in the file header because KV content is not known until finish is called and a streaming writer cannot seek back to patch the header. The trailer’s kv_offset field is the canonical indicator of KV presence; FileReader uses that field rather than the header flag.

§Examples

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

let handle = BufferHandle::new(64, MIN_BUFFER_ALIGNMENT, DeviceTag::Cpu, SyncMode::ProducerSynced)?;
let shape = Shape::new(vec![4u64, 4]).unwrap();
let desc = TensorDescriptor::new(
    1, 0, ElementType::Float32, shape, 0,
    LayoutDescriptor::RowMajor, vec![handle], None, None, None, None,
)?;
let data = vec![0u8; 64];

let file = tokio::fs::File::create("model.hrry").await?;
let mut writer = FileWriter::new(file).await?;
writer.write_tensor("embeddings", &desc, &[&data]).await?;
writer.finish(vec![
    ("model".to_string(), KvValue::String("llama-3".to_string())),
]).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.

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 recursively.

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.

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.