Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## Next

* Add `at` and `get` to `Blob` (#424).
* Optimized `sort` and `sortInPlace` for `VarArray`, `List`, `Array` (#422).
* Simplify `isSorted` logic (#421).
* Add `isSorted` to `Array` and `VarArray` (#414).
Expand Down Expand Up @@ -96,4 +97,4 @@

## 0.1.0

* Initial release
* Initial release
29 changes: 28 additions & 1 deletion src/Blob.mo
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// Module for working with Blobs (immutable sequences of bytes).
///
/// Blobs represent sequences of bytes. They are immutable, iterable, but not indexable and can be empty.
/// Blobs represent sequences of bytes. They are immutable, iterable, indexable and can be empty.
///
/// Byte sequences are also often represented as `[Nat8]`, i.e. an array of bytes, but this representation is currently much less compact than `Blob`, taking 4 physical bytes to represent each logical byte in the sequence.
/// If you would like to manipulate Blobs, it is recommended that you convert
Expand Down Expand Up @@ -69,6 +69,33 @@ module {
/// ```
public func size(blob : Blob) : Nat = blob.size();

/// Returns the byte at index `index` as an option.
/// Returns `null` when `index >= size`. Indexing is zero-based.
///
/// Example:
/// ```motoko include=import
/// let blob : Blob = "abcdefgh\08";
/// assert Blob.get(blob, 8) == ?8;
/// assert Blob.get(blob, 10) == null;
/// ```
///
/// Runtime: `O(1)`
///
/// Space: `O(1)`
public func get(blob : Blob, index : Nat) : ?Nat8 = if (index < blob.size()) ?(blob.get index) else null;

/// Returns the byte at index `index`. Indexing is zero-based.
/// Traps if `index >= size`, error message may not be descriptive.
///
/// Example:
/// ```motoko include=import
/// let blob : Blob = "abcdefgh\08";
/// assert Blob.at(blob, 8) == 8;
/// ```
///
/// Runtime: `O(1)`
public func at(blob : Blob, index : Nat) : Nat8 = blob.get index;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Realizing this might be confusing with contextual dot notation...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, you mean the missing parens?

Copy link
Collaborator

@rvanasa rvanasa Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking of the discrepancy where blob.get(i) returns a Nat8 whereas Blob.get(blob, i) would return an optional ?Nat8.

Not sure if there's much we can do about this aside from a breaking change to the compiler or using a different convention for the Blob module compared to List (which might confuse LLMs and humans).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I get it now. But the same situation probably for Text if that provides indexing at all. That wouldn't be O(1), though.


/// Creates a `Blob` from an array of bytes (`[Nat8]`), by copying each element.
///
/// Example:
Expand Down
2 changes: 2 additions & 0 deletions validation/api/api.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@
{
"name": "Blob",
"exports": [
"public func at(blob : Blob, index : Nat) : Nat8",
"public type Blob",
"public func compare(b1 : Blob, b2 : Blob) : Order.Order",
"public func empty() : Blob",
"public func equal(blob1 : Blob, blob2 : Blob) : Bool",
"public func fromArray(bytes : [Nat8]) : Blob",
"public func fromVarArray(bytes : [var Nat8]) : Blob",
"public func get(blob : Blob, index : Nat) : ?Nat8",
"public func greater(blob1 : Blob, blob2 : Blob) : Bool",
"public func greaterOrEqual(blob1 : Blob, blob2 : Blob) : Bool",
"public func hash(blob : Blob) : Types.Hash",
Expand Down