Zig Programming Language

241 readers
1 users here now

A lemm.ee community for Zig!

founded 2 years ago
MODERATORS
76
 
 

From the README:

arbor

For the future of plugin development

Goals

  • Dead-simple plugin development. Write <= 100 lines of code and have a runnable blank-slate plugin.

  • Ideally only require Zig as a toolchain dependency, not as a programming language. You should be able to write plugins in C/C++/whatever and easily link that code to Arbor via a C API and the Zig build system.

    • Could also have a get_zig.sh that will download latest stable Zig if you don't already have it
  • Easy cross-compilation. Compile to Mac/Linux/Windows from Mac/Linux/Windows, batteries included.

  • Cross-platform graphics. A simple software renderer (like Olivec), but also native graphics programming, potentially using something like sokol, or making a thin wrapper around Direct2D/CoreGraphics for cross-platform graphics abstraction, giving the programmer a simple choice with little-to-no platform-specific considerations.

  • Simple, declarative UI design. Possibly with the option of using a custom CSS-like syntax (or Ziggy) to declare, arrange, and style UI widgets at runtime or compile-time, all compiling to native code--not running in some god-forsaken web browser embedded in a plugin UI 🤮

Have:

  • A nice abstraction layer over plugin APIs which should lend itself nicely to extending support to other APIs

  • Easy comptime parameter generation

  • Basic CLAP audio plugin supporting different types of parameters, sample-accurate automation

  • A janky VST2 implementation that works in Reaper and mostly works in other DAWs

  • Simple, portable software rendering using Olivec and a custom text rendering function with a bitmap font

77
 
 

From the README:

Ly is a lightweight TUI (ncurses-like) display manager for Linux and BSD.

[...]

Ly should work with any X desktop environment, and provides basic wayland support (sway works very well, for example).

78
 
 

From the README:

A Zig wrapper around md4c for parsing Markdown.

Exposes a single function that puts a parser type together from comptime-known Zig functions. The generalisation to using vtables is left as an exercise to the user.

79
 
 

From the README:

This library provides a simple and efficient way to generate and manipulate UUIDs (Universally Unique Identifiers) in Zig.

Features

  • Generate UUIDs of all versions (1, 3, 4, 5)
  • Parse UUIDs from strings
  • Convert UUIDs to strings, 128-bit integers, and byte-arrays
  • Access to parts of UUID (time_low, time_mid, node, etc.)
80
 
 

The code in this video can be found here: https://codeberg.org/dude_the_builder/zig_master

81
 
 

From the announcement:

Regular expressions follow the PCRE syntax. This update has a full regex parser and finite-state-automaton generator that builds parsing trees at comptime. All parsing trees are stateless and have @sizeOf(T) == 0.

To use Regex, just look for the fluent.match function and provide your expression string and source string: fluent.match("[abc]\d+", str)

It’s an on going process, but it’s at a point where people can start using them and be on the lookout for more updates!


Fluent can be found on Github: https://github.com/andrewCodeDev/Fluent

82
 
 

From the README:

Tuile is a Text User Interface library written in Zig.

The only currently supported backend is ncurses [...]

83
 
 

From the README:

z2d is a 2D graphics library primarily designed around rasterizing vector primitives like lines and cubic Beziers. In other words, it's designed around supporting operations that you would see in SVG or other vector languages like PostScript or PDF.

Our drawing model is (loosely) inspired by Cairo: most operations take place through the Context, which connect Patterns (pixel/color sources) and Surfaces (drawing targets/buffers). Paths contain the vector data for filling and stroking operations. Additionally, surfaces can be interfaced with directly.

84
 
 

From the README:

Derive command line parsers from union and struct types. Provides nested, context aware usage text similar to the zig compiler. Works with existing data structures you may not control.

Features

  • field types
    • int, bool, enum, float, optional, array, slice
    • nested unions and structs
  • help / usage
    • automatically printed on parsing errors
    • very customizable
    • nested and context aware, showing only one level of help info at once
    • written to parse_options.err_writer (default std.io.null_writer)
    • accessible from any print() method: std.debug.print("{help}", .{parse_result});
  • diagnostics which clearly point to parsing errors
  • easily dump parse results
    • from any print() method: std.debug.print("{}", .{parse_result});
  • derive short names by setting clarp_options.derive_short_names and override them with FieldOption.short
  • apply clarp_options to types you don't control with parseWithOptions()
  • rename long names with FieldOption.long
  • long and short options can be parsed with any of these forms:
    Long Short
    --foo value -f value
    --foo=value -f=value
    --foovalue -fvalue

Overview

Union types create alternative commands. Commands match field names exactly.

Struct types create sequences of options. Options match field names with leading dashes such as --text_color for field text_color. Named options can be parsed out of order. Unnamed, positional parsing may be enabled by setting clarp_options.fields.<field_name>.positional.

Tuple types create unnamed sequences and are parsed strictly by position.

Bool fields create 'flags' and may be specified as --flag or true/false when unnamed. They are always optional and default to false.

Slice fields require an allocator and consume input until an argument is found which starts with '-' or end of arguments. clarp_options.end_marker may also be used to mark the end of field's arguments. This may be necessary with unnamed, positional fields. An Allocator can be passed as ParseOptions.allocator.

Zig version

This package was developed against zig version 0.12.0-dev.3594+355cceebc

Usage

You can find many examples in the tests.

Add clarp dependency

Fetch

$ zig fetch --save=clarp https://github.com/travisstaloch/clarp/archive/<commit-hash>.tar.gz

This will add the following

// build.zig.zon
.dependencies = .{
    .clarp = .{
        .url = "https://github.com/travisstaloch/clarp/archive/<commit-hash>.tar.gz",
        .hash = ...,
    },
},

Modify build.zig

// build.zig
pub fn build(b: *std.Build) void {
    const clarp = b.dependency("clarp", .{}).module("clarp");
    const exe = b.addExecutable(.{...});
    exe.root_module.addImport("clarp", clarp);
}

Full Example

This program creates a parser and dumps the result to stderr. It is available here and can be run with $ zig build test-demo -- args.

const std = @import("std");
const clarp = @import("clarp");

pub fn main() !void {
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();
    const allocator = arena.allocator();

    const ArgParser = clarp.Parser(union(enum) {
        cmd1: struct {
            foo: []const u8,
            pub const clarp_options = clarp.Options(@This()){
                .fields = .{
                    .foo = .{ .desc = "Foo desc." },
                },
            };
        },
        cmd2: struct { enum { a, b } = .a },
        pub const clarp_options = clarp.Options(@This()){
            .fields = .{
                .cmd1 = .{ .desc = "Cmd1 desc.", .short = "c1" },
                .cmd2 = .{ .desc = "Cmd2 desc.", .short = "c2" },
            },
        };
    }, .{});


    const args = try std.process.argsAlloc(allocator);
    const parsed = ArgParser.parse(args, .{
        .err_writer = std.io.getStdErr().writer().any(),
    }) catch |e| switch (e) {
        error.HelpShown => return,
        else => return e,
    };
    std.debug.print("{}\n", .{parsed});
}

clarp_options

When a struct or union contains a pub const clarp_options declaration, it changes parsing behavior. Nested structs and unions may declare their own clarp_options.

ParseOptions

Runtime parsing options. The second argument to clarp.Parser(T).parse().

ParserOptions

Comptime global parsing options. The second argument to clarp.Parser().

help flags

By default, if an arg is help, --help or -h context aware usage is displayed. You may change the help flags by passing an enum type for ParserOptions.help_type.

$ zig-out/bin/testexe help
Usage: testexe [command]

Commands:

  cmd1, c1            Cmd1 description.
  cmd2, c2            Cmd2 description.

General Options:

  help, --help, -h    Print command specific usage.

Notice how this message is derived from the union(enum) passed to clarp.Parser() above and that its clarp_options declaration affects the output, adding the c1 and c2 shorts and descriptions.

Command specific help

$ zig-out/bin/testexe cmd1 help
Usage: testexe cmd1 [options]

  Cmd1 description.

Options:

  --foo: string       Foo description.

General Options:

  help, --help, -h    Print command specific usage.

Command line examples

Here are some results from the ArgParser we defined above in Full Example.

Long names

$ zig-out/bin/testexe cmd1 --foo 'opt1 value'

cmd1: 
  foo: "opt1 value"

Short names

$ zig-out/bin/testexe c1 --foo 'opt1 value'

cmd1: 
  foo: "opt1 value"

$ zig-out/bin/testexe c2 b

cmd2: 
  0: b

Diagnostics

$ zig-out/bin/testexe foo
Usage: testexe [command]

Commands:

  cmd1, c1            Cmd1 description.
  cmd2, c2            Cmd2 description.

General Options:

  help, --help, -h    Print command specific usage.

error at argument 1: foo
                     ^~~
error: UnknownCommand
#... stack trace omitted
85
 
 

River is a dynamic tiling Wayland compositor written in Zig: https://isaacfreund.com/software/river/

Blog post about the River 0.3.0 and Waylock 1.0.0 update: https://isaacfreund.com/blog/river-0.3-waylock-1.0/

86
 
 

From the README:

Tiny and efficient rect packer. The algorithm is very similar to and is heavily inspired by rectpack2D and the blog post it's based on.

87
 
 

From the README:

ziglo is a Zig interface to liblo, an implementation of the Open Sound Control protocol. ziglo provides Zig types for liblo primitives and convenience functions for adding and querying message contents leveraging Zig’s comptime.

88
 
 

From the README:

Explore using a flex/yacc parser from zig to build a json Ast. The resulting json parser is able to parse complex json files such as twitter.json, build a std.json.Value Ast, and print it using std.json.stringify().

89
 
 

From the README:

A slightly cursed library for source-level static instrumentation in Zig.

This repository also includes a simple function-level profiler that outputs to the callgrind format, which is readable by KCacheGrind.

90
 
 

From the README:

This library creates bindings for accessing Javascript from within a WASM runtime

Calling Javascript functions from Zig is a pain. WASM has restrictions on the function API surface, and how references to the runtime environment (Javascript) can be stored. So to access Javascript functionality from Zig, you must create: a function in Zig which is friendly to call, a function export, and a function in Javascript which translates into the call you actually want.

This isn't too bad so far, but the Javascript API surface is large, has a lot of variadic functions, and accepts many types. The result is that your programming loop of just wanting to write code slows down writing a large amount of ill fitting boilerplate whenever you must cross the Zig to Javascript boundary.

This package is clearly inspired by Go's solution to this problem: https://pkg.go.dev/syscall/js

91
 
 

Work-in-progress Python 3.10 Interpreter written in Zig

92
 
 

A time library written in zig, licenced under MIT

93
 
 

Musa is a Wayland compositor with external window managers and first-class multiseat support. Musa is slowly approaching daily usability, but there's still a long way to a polished compositor.

Inspired by River

94
 
 

From the README:

zcrun

a simple linux container runtime built with zig

Features

  • namespaces:
    • isolate network, pid, mount, and uts namespace
  • cgroups:
    • support cgroups v2
    • limit memory, cpu, or pids (# of procs).
  • internet access inside containers using SNAT

Usage

[!NOTE] make sure that ip forwarding is enabled to be able to access the internet inside containers. run sysctl net.ipv4.ip_forward to check if it is enabled. if not, run sudo sysctl -w net.ipv4.ip_forward=1 to enable it.

[!Important] zcrun must be run as root

$ mkdir rootfs
# export container rootfs dir using docker
$ docker export $(docker create busybox) | tar -C rootfs -xvf -
# run the container using zcrun
# zcrun run <name>  <rootfs> <cmd>
$ zcrun run busybox rootfs   sh

Dependencies:

  • The iptables command.
  • Zig. This branch was tested using version 0.12.0-dev.3191+9cf28d1e9.
95
 
 

From the README:

A gap buffer is like a std.ArrayList, except that rather than having one contiguous block of items, there are two, with a moveable “gap” between them. Although moving the gap requires a copy, insertions and deletions at either side of the gap become O(1) operations.

This repository implements managed, unmanaged and optionally aligned versions of GapBuffer(T). The API is directly inspired by std.ArrayList. The main differences are “Before” and “After” versions of operations that operate or affect the gap—“Before” operations will add or remove elements before the gap. There are also convenience functions for translating a “logical” index into an offset, an element, or a pointer from the buffer, allowing the user to be largely agnostic about the location of the gap.

96
 
 

Additional cross-platform SIMD support for Zig.

Based loosely on Google Highway

97
 
 

From the README:

zig-router

Straightforward HTTP-like request routing.


Project is tested against zig 0.12.0-dev.2341+92211135f

Sample

const router = @import("zig-router");

const MyJsonBody = struct {
    float: f32,
    text: []const u8,
    number_with_default: u32 = 42,
};

fn putJson(body: MyJsonBody) !Response {
    log.info("float: {}", .{body.float});
    log.info("text: {s}", .{body.text});
    log.info("number_with_default: {}", .{body.number_with_default});
    return .{ .body = "ok" };
}

const MyPathParams = struct {
    id: []const u8,
    bundle: u32,
};

fn getDynamic(params: MyPathParams) !Response {
    log.info("id: {s}", .{params.id});
    log.info("bundle: {}", .{params.bundle});
    return .{};
}

const MyQuery = struct {
    id: []const u8 = "plz give me a good paying stable job",
    bundle: u32 = 42,
};

fn getQuery(query: MyQuery) !Response {
    log.info("id: {s}", .{query.id});
    log.info("bundle: {}", .{query.bundle});
    return .{};
}

fn getError() !void {
    return error.EPIC_FAIL;
}

fn onRequest(arena: *std.heap.ArenaAllocator, request: Request) !void {
    router.Router(.{
        router.Decoder(.json, router.JsonBodyDecoder(.{}, 4096).decode),
    }, .{
        router.Route(.PUT, "/json", putJson, .{}),
        router.Route(.GET, "/dynamic/:id/paths/:bundle", getDynamic, .{}),
        router.Route(.GET, "/query", getQuery, .{}),
        router.Route(.GET, "/error", getError, .{}),
    }).match(arena.allocator(), .{
        .method = request.method,
        .path = request.path,
        .query = request.query,
        .body = .{ .reader = request.body.reader() }
    }, .{ arena.allocator() }) catch |err| switch (err) {
        error.not_found => return .{ .status = .not_found },
        error.bad_request => return .{ .status = .bad_request },
        else => return err,
    };
}

Depend

build.zig.zon

.zig_router = .{
  .url = "https://github.com/Cloudef/zig-router/archive/{COMMIT}.tar.gz",
  .hash = "{HASH}",
},

build.zig

const zig_router = b.dependency("zig_router", .{}).module("zig-router");
exe.root_module.addImport("zig-router", zig_router);
98
 
 

Budoux for Zig (and C)

Original library from Google: https://github.com/google/budoux

99
 
 

zat is a syntax highlighting cat like utility.

It uses tree-sitter and supports for vscode themes.

100
 
 

From the README:

Z-labs blog post - Running BOFs with 'bof-launcher' library

Introduction

Cobalt Strike 4.1 released on 25 June 2020, introduced a novel (for that time) capability of running so called Beacon Object Files - small post-ex capabilities that execute in Beacon, parse arguments, call a few Win32 APIs, report output, and exit. Since that time BOFs became very popular and the demand to launch/execute them in other environments than Cobalt Strike's Beacon has emerged.

Purpose

We at Z-Labs saw a big potential in BOFs and decided to extend its capabilities, versatility and usefulness even further. That's how this project came to live.

bof-launcher is an open-source library for loading, relocating and launching BOFs on Windows and UNIX/Linux systems. It's an alternative to Trustedsec's COFFLoader and ELFLoader with some very interesting features:

  • Fully compatibile with Cobalt Strike's Beacon. Can compile and run every BOF available at Cobalt Strike Community Kit and every other open-source BOF that adheres to generic BOF template.
  • Distributed as a fully standalone library with zero dependency (it does not even use libc).
  • Fully integrable with programs written in C/C++ and/or Zig progamming languages.
  • Adds capability to write BOFs in Zig programming language - which is a low-level langauge with a goal of being a "better C". All the features of the language and rich standard library can be used in BOFs (hash maps and other data structures, cross-platform OS layer, http, networking, threading, crypto and more).
  • Asynchronous BOF execution - capability to launch more time-consuming BOFs in a separate thread.
  • BOF process injection - capability to launch more risky BOFs (i.e. privilege escalation exploits) by injecting it to a new process.
  • Seamless support for either Windows COFF and UNIX/Linux ELF formats.
  • ARM and AARCH64 support on Linux.
  • Used in our cli4bofs tool that allows for running BOF files directly from a filesystem.
  • Very flexible and efficient API allowing for so called BOF chaining.
view more: ‹ prev next ›