Skip to content

Instantly share code, notes, and snippets.

@mtso
Last active June 10, 2023 00:28
Show Gist options
  • Save mtso/bfb11917bff73dbff768cffb0822bd29 to your computer and use it in GitHub Desktop.
Save mtso/bfb11917bff73dbff768cffb0822bd29 to your computer and use it in GitHub Desktop.
const std = @import("std");
const Duck = struct {
name: []const u8,
grade: u8 = undefined,
};
const DuckGrader = struct {
pub fn grade(_: *DuckGrader, duck: *Duck) void {
duck.grade = if (duck.name.len > 1) duck.name[0] else 'Z';
}
};
const DuckCounter = struct {
count: u32 = 0,
pub fn count(self: *DuckCounter, _: *const Duck) void {
self.count += 1;
}
};
const DuckAnnouncer = struct {
pub fn announce(_: *DuckAnnouncer, duck: *const Duck) void {
std.debug.print("{s} has joined the flock! Grade: {c}\n", .{ duck.name, duck.grade });
}
};
const DuckFarm = struct {
observers: []Observer,
observer_count: usize = 0,
const Observer = struct {
context: usize,
callback: *const fn (context: usize, duck: *Duck) void,
};
fn produce(self: *DuckFarm, name: []const u8) void {
var duck = Duck{ .name = name };
self.notifyObservers(&duck);
}
fn notifyObservers(self: *DuckFarm, duck: *Duck) void {
for (self.observers[0..self.observer_count]) |observer| {
observer.callback(observer.context, duck);
}
}
fn addObserver(self: *DuckFarm, context: anytype, callback: fn (@TypeOf(context), *Duck) void) void {
std.debug.assert(self.observer_count < self.observers.len);
self.observers[self.observer_count] = .{
.context = @ptrToInt(context),
.callback = struct {
fn wrapper(ctx: usize, d: *Duck) void {
callback(@intToPtr(@TypeOf(context), ctx), d);
}
}.wrapper,
};
self.observer_count += 1;
}
};
pub fn main() void {
var observers = [_]DuckFarm.Observer{undefined} ** 3;
var farm = DuckFarm{ .observers = &observers };
var counter = DuckCounter{};
var announcer = DuckAnnouncer{};
var grader = DuckGrader{};
farm.addObserver(&grader, DuckGrader.grade);
farm.addObserver(&counter, DuckCounter.count);
farm.addObserver(&announcer, DuckAnnouncer.announce);
farm.produce("Albert");
farm.produce("Bernie");
std.debug.print("Ducks produced: {d}\n", .{counter.count});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment