Issuing or solving (?) issues 😄
- Dominant language
- No language data
- Stars
- 4
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
## Update ArrayList to 0.15.1
Gaining 1% of `Zig` knowledge more...
Review of some powerful `Zig` concepts for safety:
- slice ownership
- Errors and `try/catch`
- optionals (`null`)
- `defer` and `errdefer`
## 1) `[]u8` vs `[]const u8` and `ArrayList`: ownership and mutability
A "slice" is a pointer to a sequence (`T` is a type, like `void`, `u8` etc..., and `usize` is the OS dependent size of a pointer address).
```zig
struct {
ptr: [*]T, // a pointer to a sequence of T of unknown length
len: usize,
}
```
- `[]const u8` is a pointer to __read-only-slice__, a fixed unknown size sequence of `u8`s. No memory to free.
```zig
const hello: []const u8 = "Hello"; // String literals
// ❌ Compile error
// hello[0] = 'h';
// ✅ : can slice
std.debug.print("{c}, {s}\n", .{hello[0], hello[1..4]})
// => "h", "ello"
print("{?}, {?}, {d}, {c}\n", .{@TypeOf(bonjour), bonjour.ptr, bonjour.len});
// => []const u8, u810255, 5
```
- `[]u8`: mutable slice of _fixed unknown_ size. It is allocated, it must be freed.
```zig
// ❌ Compile error
const hi: []u8 = "hello"
const buffer: []u8 = try allocator.alloc(u8, 5);
defer allocator.free(buffer); // ⚠️ if not, "(err): memory address 0x7f08 leaked:"
// ✅
buffer[0] = 'H'; // ‼️ note the single quotes for byte/character literal
// because "H" is of type '*const [1:0]u8', thus a pointer
// ✅
@memcpy(buffer, "hello");
std.debug.print("{s}\n", .{buffer});
// => "hello"
```
>[!IMPORTANT]
> Receiving mutable slices usually means "you own this memory".
> If a function returns an allocated slice (`[]T`), the caller owns it and must free it.
> f the function returns a const slice (`[]const T`), it’s usually just a view into existing data (no freeing needed unless explicitly documented).
Example: the caller uses the function below that returns a mutable slice allocated by an allocator.
```zig
/// Caller owns the returned slice and must free it with `allocator.free`.
pub fn createMessage(allocator: std.mem.Allocator, text: []const u8) ![]u8 {
const msg = try allocator.alloc(u8, text.len + 1); // +1 for null terminator
@memcpy(msg[0..text.len], text);
msg[text.len] = 0; // Null-terminate (optional)
return msg;
}
```
The caller does:
```zig
pub fn main() !void {
const allocator = std.heap.page_allocator;
const greeting = try createMessage(allocator, "hello");
defer allocator.free(greeting); // <-- Explicit cleanup required.
std.debug.print("Message: {s}\n", .{greeting});
}
```
>[!WARNING]
>__Edge case__: Null-terminated strings: If working with `C` interop, ensure the allocator matches (e.g., `allocator.allocSentinel(u8, len, 0)` for `C`-style strings).
- `ArrayList`? A dynamic sized (of type `array_list.
```zig
/// Returns an ArrayList whose memory is managed by the caller (must call `.deinit()`).
pub fn buildMessage(allocator: std.mem.Allocator, text: []const u8) !std.ArrayList(u8) {
var list: std.ArrayList(u8) = .empty;
try list.appendSlice(allocator, text);
try list.append(allocator, 0); // Null-terminate (optional)
return list; // Caller must call `list.deinit(allocator)`.
}
```
The caller frees it with `.deinit(allocator)` and elements are reached with `.items`:
```zig
pub fn main() !void {
const allocator = std.heap.page_allocator;
var message = try buildMessage(allocator, "world");
defer message.deinit(allocator); // Cleanup is explicit but managed by ArrayList.
std.debug.print("Message: {s}\n", .{message.items});
std.debug.print("elt: {c}\n", .{message.items[0]});
}
//=> "world"
//=> "w"
```
- String literals? A pointer to a null terminated array
```zig
const hello = "hello";
std.debug.print("{?}\n", .{@TypeOf(hello)});
// *const[5:0]u8
```
>[!NOTE]
> You can convert a string literal into a slice:
```zig
const hello_slice: []const u8 = hello;
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.