You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: content/2025-08-20-heapless-091.md
+48-25Lines changed: 48 additions & 25 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,20 +6,18 @@ in_search_index = true
6
6
template = "page.html"
7
7
+++
8
8
9
-
# Heapless `0.9.1` released
10
-
11
-
Almost 2 years after the last release, the [heapless](https://github.com/rust-embedded/heapless). The first attempt at a `0.9.0` release was yanked, due to including more breaking changes than intended. This has been fixed, and `0.9.1` has been released today.
9
+
Almost 2 years after the last release, the [heapless](https://github.com/rust-embedded/heapless) crate has a new release. The first attempt at a `0.9.0` release was yanked due to including more breaking changes than intended. This has been fixed, and `0.9.1` has been released today.
12
10
13
11
Compared to `0.8.0`, the `0.9.1` release contains a bunch of small everyday improvements and bugfixes. Most users of the library should be able to adapt with minimal changes. For more information, you can check out [the changelog](https://github.com/rust-embedded/heapless/blob/main/CHANGELOG.md). Here are some of the major changes that can improve your usage of the library.
14
12
15
13
<!-- more -->
16
14
17
15
# The `View` types
18
16
19
-
One of the main constraints when working with `heapless` types is that they all have a `const generic`. In a lot of situations, these can be removed thanks to the `View` types.
17
+
One of the main constraints when working with `heapless` types is that they all have a `const generic`. In a lot of situations, these can now be removed thanks to the `View` types.
20
18
21
-
A lot of embedded firmware will allocated a couple of buffers and pass them around to save on memory.
22
-
To make it easy to change the size of the buffers, a lot of functions will carry along these `const generics`:
19
+
A lot of embedded firmware will allocate a couple of buffers and pass them around to save on memory.
20
+
To make it easy to change the size of the buffers, functions will carry along these `const generics`:
The new `View` variants of the types will enable you to remove the `const generics` while still keeping the same functionality:
35
+
The new `View` variants of the types enable you to remove the `const generics` while still keeping the same functionality:
38
36
39
37
```rust
40
38
useheapless::VecView;
@@ -49,10 +47,13 @@ impl App {
49
47
}
50
48
```
51
49
52
-
Callsites of the `handle_request` will essentially be able to stay the same, the function will continue to accept `Vec<u8, N>`. So what's the difference between `VecView` and `Vec`?
53
-
There are almost none, both are aliases of the same underlying type `VecInner`. The only limitation that `VecView` has compared to `Vec` is that `VecView` is `!Sized`. This means that you cannot perform anything that would require the compiler to know the size of the `VecView` at compile-time. In practice, you will always need to manipulate `VecView` through pointer indirection (generally a reference). This means you can't just create a `VecView` out of thin air, the `VecView` is a runtime "View" of an existing `Vec`.
50
+
Call sites of `handle_request` will be able to stay the same. The function will continue to accept `&mut Vec<u8, N>`.
51
+
52
+
So what's the difference between `VecView` and `Vec`?
54
53
55
-
So how can we obtain a `VecView` ? It's pretty simple: `Vec` can be *coerced* into a `VecView`. [Coercion](https://doc.rust-lang.org/reference/type-coercions.html) (in this case [`Unsized` coercion](https://doc.rust-lang.org/reference/type-coercions.html#r-coerce.unsize)), is a way the compiler can transform one type into another implicitely. In this case, the compiler is capable of converting pointers to a `Vec` (`&Vec<T>`, `&mut Vec<T>`, `Box<T>` etc...) to pointers to a `VecView`, so you can use a reference to a `Vec` when a reference to a `VecView` is exepected:
54
+
There are almost none, both are aliases of the same underlying type `VecInner`. The only limitation of `VecView` compared to `Vec` is that `VecView` is `!Sized`. This means that you cannot perform anything that would require the compiler to know the size of the `VecView` at compile-time. You will always need to manipulate `VecView` through pointer indirection (generally a reference). This means you can't just create a `VecView` out of thin air. The `VecView` is always a runtime "View" of an existing `Vec`.
55
+
56
+
So how can we obtain a `VecView` ? It's pretty simple: `Vec` can be *coerced* into a `VecView`. Coercion (in this case [`Unsized` coercion](https://doc.rust-lang.org/reference/type-coercions.html#r-coerce.unsize)), is a way the compiler can transform one type into another implicitly. In this case, the compiler is capable of converting pointers to a `Vec` (`&Vec<T, N>`, `&mut Vec<T, N>`, `Box<Vec<T, N>>` etc...) to pointers to a `VecView` (`&VecView<T>`, `&mut VecView<T>`, `Box<VecView<T>>` etc...), so you can use a reference to a `Vec` when a reference to a `VecView` is expected:
If you prefer things to be explicit, the `View` variants of types (`Vec` is not the only datastructure having `View` variants) can be obtained through `vec.as_view()` or through `vec.as_mut_view()`.
76
+
If you prefer things to be explicit, the `View` variants of types (`Vec` is not the only data structure having `View` variants) can be obtained through `vec.as_view()` or through `vec.as_mut_view()`.
76
77
77
78
The pointer to the `VecView` is the size of 2 `usize`: one for the address of the underlying `Vec`, and one for the capacity of the underlying `Vec`. This is exactly like slices. `VecView<T>` is to `Vec<T, N>` what a slice `[T]` is to an array `[T; N]`.
78
79
Unless you need to store data on the stack, most often you will pass around `&mut [T]` rather than `&mut [T; N]`, because it's simpler. The same applies to `VecView`. Wherever you use `&mut Vec<T, N>`, you can instead use `&mut VecView<T>`.
79
80
80
-
The `View` types are not available just for `Vec`. There are `View` versions of a lot of heapless types.
81
+
The `View` types are not available just for `Vec`. There are `View` versions of a lot of heapless types:
82
+
-`Vec` has `VecView`
83
+
-`String` has `StringView`
84
+
-`Deque` has `DequeView`
85
+
-`LinearMap` has `LinearMapView`
86
+
-`HistoryBuf` has `HistoryBufView`
87
+
-`BinaryHeap` has `BinaryHeapView`
88
+
-`mpmc::Queue` has `mpmc::QueueView`
89
+
-`spsc::Queue` has `spsc::QueueView`
90
+
(and now, the producer and consumer structs don't carry the const-generic)
91
+
-`SortedLinkedList` has `SortedLinkedListView`
92
+
93
+
`IndexMap` and `IndexSet` are the two remaining structures that don't have a `View` type available.
94
+
We hope to be able to use it in the future.
81
95
82
96
## Benefits of the view types
83
97
84
98
The benefits are multiple:
85
99
86
100
### Better compatibility with `dyn Traits`
87
101
88
-
If a trait has a function that takes a generic, it is not `dyn` compatible. By removing the const generic, the `View` types can make `dyn Trait` can pass around data structures without having to hard-code a single size of buffer in the trait definition.
89
-
90
-
### Better ergonomics
91
-
92
-
The View types can remove a ton of excess noise from the generics.
102
+
If a trait has a function that takes a generic, it is not `dyn` compatible. By removing the const generic, the `View` types can make `dyn Trait` pass around data structures without having to hard-code a single size of buffer in the trait definition.
93
103
94
104
### Better binary size and compile times
95
105
96
106
When you use const-generics, the compiler needs to compile a new version of the function for each value of the const-generic.
97
-
Removing the const generic means cutting down on duplicated function that are all almost the same, which improves both compile time and the size of the resulting binary.
107
+
Removing the const generic means cutting down on duplicated functions that are all almost the same, which improves both compile time and the size of the resulting binary.
108
+
109
+
### Better ergonomics
110
+
111
+
The View types can remove a ton of excess noise from the generics.
98
112
99
113
# The `LenType` optimization
100
114
101
115
Most often, buffers in embedded applications will not contain a huge number of items.
102
-
However, until `0.9.1` their capacity was almost always stored as a `usize`, which can often encode much more values than necessary.
116
+
Until `0.9.1` the capacity of the `heapless` data structures were almost always stored as a `usize`, which can often encode much more values than necessary.
117
+
118
+
In 0.9.1, data structures now have a new optional generic parameter called `LenT`. This type accepts `u8`, `u16`, `u32`, and `usize`, and defaults to `usize` to keep typical uses of the library, simple.
119
+
120
+
If you are seriously constrained by memory, a `Vec<T, 28>` (equivalent to `Vec<T, 28, usize>`) can become a `Vec<T, 28, u8>`, saving up to 7 bytes per `Vec`. This is not much, but in very small microcontrollers, it can make the difference between a program that uses all the memory available and one that just fits.
121
+
122
+
# Contributors
103
123
104
-
In 0.9.1, most data structures now have a new optional generic parameter called `LenT`. This type accepts `u8`, `u16`, `u32`, and `usize`, and defaults to `usize`to keep uses of the library simple.
124
+
This release was made possible by [@Zeenix] joining the embedded working group as part of the libs team to help maintain `heapless` and convincing [@sgued]to do the same.
105
125
106
-
If you are seriously constrained by memory, a `Vec<T, 28>` can become a `Vec<T, 28, u8>`, saving up to 7 bytes per `Vec`. This is not much, but in very small microcontrollers it can make the difference between a program that uses all the memory available and one that just fits.
126
+
The `View` types were a contributions from [@sgued], and the `LenType` were contributed by [@GnomedDev].
127
+
In total 38 contributors participated in all the other improvements to the crate and helped with maintainance.
107
128
108
-
This release was made possible by [@sgued] and [@zeenix] joining the embedded working group as part of the libs team.
0 commit comments