Single Ownership: Owned<T>

Owned marks a variable as the one place a piece of data “lives.” When you hand that data to another variable or function, ownership moves with it — and the original becomes off-limits, so two parts of your code can’t both think they’re in charge of the same memory.

Note

Who this is for. This is part of Cuttlefish’s optional ownership system. You only need it when you’re moving chunks of data (arrays, buffers, objects) around and want the tool to flag mix-ups. For plain numbers and booleans, skip it.

Why use Owned

In standard JavaScript, objects are shared automatically via references. In embedded C++, that freedom can lead to two parts of your code modifying the same memory at once and corrupting it. Owned enforces a strict single-owner rule, so there’s never any doubt about who’s in charge.


Move Semantics

When you assign an Owned variable to another variable or pass it to a function, ownership is moved. The original variable is invalidated.

Example: Ownership Transfer

import { Owned } from '@typecad/hal';

const buffer: Owned<Uint8Array> = new Uint8Array([1, 2, 3]);

// Ownership is transferred to 'movedBuffer'
const movedBuffer = buffer; 

// ERROR: 'buffer' was moved and cannot be used again. [ownership-use-after-move]
console.log(buffer[0]); 

Error: ownership-use-after-move

This error occurs when you attempt to read from or write to a variable that has already transferred its ownership.

How to fix:

  • If you still need the data in the original variable, create a Shared (borrow) before moving.
  • If you truly need two copies, perform an explicit copy (e.g., new Uint8Array(original)).

C++ Copy Warnings

Because Cuttlefish targets resource-constrained hardware, it does not use complex C++ move constructors or std::move.

Info: ownership-owned-copy

When you move a non-primitive Owned variable into an unannotated variable, the transpiler warns you that a C++ copy is being created.

const src: Owned<Uint8Array> = new Uint8Array([1, 2, 3]);
const copy = src; // INFO: Moving 'src' into 'copy' creates a C++ copy.

How to fix: If you intended to share the data without copying, use a Shared:

const view: Shared = src; // Zero-copy borrow

API Summary

FeatureDescription
Move on AssignmentAssigning a = b where b is Owned invalidates b.
Move on CallPassing an Owned variable as a parameter transfers ownership to the function.
Return OwnershipFunctions can return Owned<T> to transfer ownership back to the caller.

Best Practices

  1. Pass by Owned only when the function needs to store the data long-term or destroy it.
  2. Pass by Shared for temporary reading (most common).
  3. Pass by Mut for temporary in-place modification.