Last active
November 21, 2024 21:47
-
-
Save jdmichaud/b75ee234bfa87283a6337e06a3b70767 to your computer and use it in GitHub Desktop.
Zig cheatsheet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| |
https://ziglang.org/documentation/master/#Pointers | |
*T - single-item pointer to exactly one item. | |
Supports deref syntax: ptr.* | |
[*]T - pointer to unknown number of items. (eq. of *T in C) | |
Supports index syntax: ptr[i] | |
Supports slice syntax: ptr[start..end] | |
Supports pointer arithmetic: ptr + x, ptr - x | |
T must have a known size, which means that it cannot be anyopaque or any other opaque type. | |
*[N]T - pointer to N items, same as single-item pointer to an array. | |
Supports index syntax: array_ptr[i] | |
Supports slice syntax: array_ptr[start..end] | |
Supports len property: array_ptr.len | |
[]T - pointer to runtime-known number of items. | |
Supports index syntax: slice[i] | |
Supports slice syntax: slice[start..end] | |
Supports len property: slice.len | |
https://github.com/ziglang/zig/wiki/Zig-Newcomer-Programming-FAQs#what-is-a-t | |
What's inside the `[.]T` is the number of items. | |
`[n]T` is an array with a compile time known number of items. | |
`[*]T` means the number is indeterminate (like a kleene star). It's a pointer to an array of unknown size. | |
`[]T` is a slice, meaning it's a struct with a `[*]` and a size_t for the runtime known size of the array. | |
```c | |
const arr = [_]u8{ 5, 1, 8, 4, 5, 6 }; | |
std.log.debug("arr: {}", .{ @TypeOf(arr) }); | |
std.log.debug("&arr: {}", .{ @TypeOf(&arr) }); | |
const sli: []const u8 = &arr; | |
std.log.debug("sli: {}", .{ @TypeOf(sli) }); | |
std.log.debug("sli[0..]: {}", .{ @TypeOf(sli[0..]) }); | |
std.log.debug("sli[0..].*: {}", .{ @TypeOf(sli[0..].*) }); | |
var known_at_runtime_zero: usize = 3; | |
_ = &known_at_runtime_zero; | |
std.log.debug("sli[known_at_runtime_zero..][0..3].*: {}", .{ @TypeOf(sli[known_at_runtime_zero..][0..3].*) }); | |
``` | |
This will give: | |
``` | |
arr: [6]u8 | |
&arr: *const [6]u8 | |
sli: []const u8 | |
sli[0..]: *const [6]u8 | |
sli[0..].*: [6]u8 | |
``` | |
Zig automatically converts &arr which is a pointer on the static array to a slice. | |
A slice is a (sort of) struct containing a pointer and a size (known at compile time here). | |
Then using `[0..]` we extract the pointer from the slice and with `.*` we dereference it back to a static array. | |
When the start position is known at runtime, we can still extract comptime known length slice by double slicing. | |
First from the runtime start position then from 0 to a static value. This gets us a comptime known array. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Allocate a slice | |
const slice: []const u8 = try allocator.alloc(u8, 256); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
pub fn main() !void { | |
var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){}; | |
const allocator = general_purpose_allocator.allocator(); | |
const args = try std.process.argsAlloc(allocator); | |
defer std.process.argsFree(allocator, args); | |
const stdout = std.io.getStdOut().writer(); | |
if (args.len != 1 and (std.mem.eql(u8, args[1], "--help") or std.mem.eql(u8, args[1], "-h"))) { | |
try stdout.print("{s} is a nice tool\n\n", .{ args[0] }); | |
try stdout.print("usage:\n", .{}); | |
try stdout.print(" {s} - Do something\n", .{ args[0] }); | |
try stdout.print(" {s} parameter - Do something with a parameter\n", .{ args[0] }); | |
return; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Convert a slice of type A to a slice of type B | |
const src: []const u8 = ...; | |
const dest: []const u32 = @as(*const []const u32, @ptrCast(&src[0..])).*; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Create a folder | |
const cwd = std.fs.cwd(); | |
try cwd.makeDir("folder_name"); | |
// Iterate over directory content... | |
var iter_dir = try std.fs.cwd().openIterableDir( | |
"folder_name", | |
.{}, | |
); | |
// ...and count the number of files | |
var file_count: usize = 0; | |
var iter = iter_dir.iterate(); | |
while (try iter.next()) |entry| { | |
if (entry.kind == .file) file_count += 1; | |
} | |
// reference: https://zig.guide/standard-library/filesystem/ | |
// Create a file | |
const file = try std.fs.cwd().createFile( | |
"somefile.txt", | |
.{ .read = true }, | |
); | |
defer file.close(); | |
// Get file stats | |
const stat = try file.stat(); | |
try expect(stat.size == 0); | |
try expect(stat.kind == .file); | |
try expect(stat.ctime <= std.time.nanoTimestamp()); | |
try expect(stat.mtime <= std.time.nanoTimestamp()); | |
try expect(stat.atime <= std.time.nanoTimestamp()); | |
// Read file | |
const contents = try file.reader().readAllAlloc( | |
test_allocator, | |
256, // read 256 characters | |
); | |
defer test_allocator.free(contents); | |
// Write to file | |
const file = try std.fs.cwd().createFile( | |
"someotherfile.txt", | |
.{ .read = true }, | |
); | |
defer file.close(); | |
try file.writeAll("Some content"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const PakHeader = extern struct { | |
magic: [4]u8, | |
offset: u32, | |
size: u32, | |
}; | |
const pak: []const u8 = ...; | |
const pakHeader: *const PakHeader = @ptrCast(&pak[0]); | |
try stdout.print("magic: {s}\n", .{ pakHeader.magic }); | |
try stdout.print("offset: {}\n", .{ pakHeader.offset }); | |
try stdout.print("size: {}\n", .{ pakHeader.size }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
fn load(pathname: []const u8) ![]align(4096) const u8 { | |
var file = try std.fs.cwd().openFile(pathname, .{}); | |
defer file.close(); | |
const size = try file.getEndPos(); | |
const buffer = try std.posix.mmap( | |
null, | |
size, | |
std.posix.PROT.READ, | |
.{ .TYPE = .SHARED }, | |
file.handle, | |
0, | |
); | |
errdefer std.posix.munmap(buffer); | |
return buffer; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// import ctypes | |
// | |
// class Quux(Structure): | |
// _pack_ = 1 # Necessary if your structure in align(1) in zig | |
// _fields_ = [ | |
// ("field", c_uint32), | |
// ] | |
// | |
// lib = ctypes.CDLL("./libpython.so") | |
// # for ctypes everything is a i32, so this is necessary | |
// # to pass around 64 bits pointers | |
// lib.foo.restype = ctypes.c_void_p | |
// f = lib.foo() | |
// lib.bar.argtypes = (ctypes.c_void_p,) | |
// lib.bar(f) | |
// | |
// Build with: `zig build-lib python.zig -dynamic` | |
var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){}; | |
const allocator = general_purpose_allocator.allocator(); | |
// This function is extern and can be access directly by python | |
const Quux = extern struct { | |
field: u32, | |
}; | |
// This struct is not extern and cannot be accessed directly. | |
// Use pointers as handlers. | |
const Foo = struct { | |
quuxes: []const Quux, | |
pub fn init() Foo { | |
const quuxes = &[_]Quux{ Quux{ .field = 42 } }; | |
return Foo{ | |
.quuxes = quuxes, | |
}; | |
} | |
}; | |
// This function is exported and accessible by python using ctypes | |
export fn foo() *Foo { | |
var f: *Foo = allocator.create(Foo); | |
f.* = Foo.init(); | |
return &f; | |
} | |
// This function is exported and accessible by python using ctypes | |
export fn bar(f: *Foo) void { | |
std.log.debug("f.quuxes {any}", .{ f.quuxes[0] }); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ref: https://zig.guide/standard-library/readers-and-writers/ | |
fn nextLine(reader: anytype, buffer: []u8) !?[]const u8 { | |
var line = (try reader.readUntilDelimiterOrEof( | |
buffer, | |
'\n', | |
)) orelse return null; | |
// trim annoying windows-only carriage return character | |
if (@import("builtin").os.tag == .windows) { | |
return std.mem.trimRight(u8, line, "\r"); | |
} else { | |
return line; | |
} | |
} | |
pub fn main() !void { | |
const stdout = std.io.getStdOut(); | |
const stdin = std.io.getStdIn(); | |
try stdout.writeAll( | |
\\ Enter your name: | |
); | |
var buffer: [100]u8 = undefined; | |
const input = (try nextLine(stdin.reader(), &buffer)).?; | |
try stdout.writer().print( | |
"Your name is: \"{s}\"\n", | |
.{input}, | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment