Fix documentation / tidy up code
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details

This commit is contained in:
kayomn 2022-11-04 10:38:37 +00:00
parent 4bb86c41bc
commit 4f0224a029
6 changed files with 57 additions and 34 deletions

View File

@ -151,8 +151,6 @@ pub const Writer = meta.Function([]const u8, usize);
/// ///
/// Returns a sliced reference of the raw bytes in `pointer`. /// Returns a sliced reference of the raw bytes in `pointer`.
/// ///
/// **Note** that passing a slice will convert it to a byte slice.
///
pub fn bytesOf(pointer: anytype) switch (@typeInfo(@TypeOf(pointer))) { pub fn bytesOf(pointer: anytype) switch (@typeInfo(@TypeOf(pointer))) {
.Pointer => |info| if (info.is_const) []const u8 else []u8, .Pointer => |info| if (info.is_const) []const u8 else []u8,
else => @compileError("`pointer` must be a pointer type"), else => @compileError("`pointer` must be a pointer type"),
@ -254,8 +252,10 @@ test "fill" {
} }
/// ///
/// Searches for the first instance of an `Element` equal to `needle` in `haystack`, returning its /// Linearly searches for the first instance of an `Element` equal to `needle` in `haystack`,
/// index or `null` if nothing was found. /// returning its index or `null` if nothing was found.
///
/// **Note** that this operation has `O(n)` time complexity.
/// ///
pub fn findFirst(comptime Element: type, haystack: []const Element, pub fn findFirst(comptime Element: type, haystack: []const Element,
needle: Element, comptime testEquality: fn (Element, Element) bool) ?usize { needle: Element, comptime testEquality: fn (Element, Element) bool) ?usize {
@ -282,6 +282,8 @@ test "findFirst" {
/// Searches for the first instance of an `Element` sequence equal to the contents of `needle` in /// Searches for the first instance of an `Element` sequence equal to the contents of `needle` in
/// `haystack`, returning the starting index or `null` if nothing was found. /// `haystack`, returning the starting index or `null` if nothing was found.
/// ///
/// **Note** that this operation has `O(nm)` time complexity.
///
pub fn findFirstOf(comptime Element: type, haystack: []const Element, pub fn findFirstOf(comptime Element: type, haystack: []const Element,
needle: []const Element, comptime testEquality: fn (Element, Element) bool) ?usize { needle: []const Element, comptime testEquality: fn (Element, Element) bool) ?usize {

View File

@ -1,6 +1,7 @@
const std = @import("std"); const std = @import("std");
const testing = @import("./testing.zig"); const testing = @import("./testing.zig");
// TODO: Remove stdlib dependency.
pub const IntFittingRange = std.math.IntFittingRange; pub const IntFittingRange = std.math.IntFittingRange;
/// ///

View File

@ -46,22 +46,23 @@ pub fn Fixed(comptime Element: type) type {
} }
/// ///
/// Attempts to push `element` into `self`, returning a [PushError] if it failed. /// Attempts to push `element` into `self`, returning a [FixedPushError] if it failed.
/// ///
pub fn push(self: *Self, element: Element) PushError!void { pub fn push(self: *Self, element: Element) FixedPushError!void {
if (self.isFull()) return error.OutOfMemory; if (self.isFull()) return error.BufferOverflow;
self.buffer[self.filled] = element; self.buffer[self.filled] = element;
self.filled += 1; self.filled += 1;
} }
/// ///
/// Attempts to push all of `elements` into `self`, returning a [PushError] if it failed. /// Attempts to push all of `elements` into `self`, returning a [FixedPushError] if it
/// failed.
/// ///
pub fn pushAll(self: *Self, elements: []const Element) PushError!void { pub fn pushAll(self: *Self, elements: []const Element) FixedPushError!void {
const filled = (self.filled + elements.len); const filled = (self.filled + elements.len);
if (filled > self.buffer.len) return error.OutOfMemory; if (filled > self.buffer.len) return error.BufferOverflow;
io.copy(Element, self.buffer[self.filled ..], elements); io.copy(Element, self.buffer[self.filled ..], elements);
@ -69,13 +70,13 @@ pub fn Fixed(comptime Element: type) type {
} }
/// ///
/// Attempts to push `count` instances of `element` into `self`, returning a [PushError] if /// Attempts to push `count` instances of `element` into `self`, returning a
/// it failed. /// [FixedPushError] if it failed.
/// ///
pub fn pushMany(self: *Self, element: Element, count: usize) PushError!void { pub fn pushMany(self: *Self, element: Element, count: usize) FixedPushError!void {
const filled = (self.filled + count); const filled = (self.filled + count);
if (filled > self.buffer.len) return error.OutOfMemory; if (filled > self.buffer.len) return error.BufferOverflow;
io.fill(Element, self.buffer[self.filled ..], element); io.fill(Element, self.buffer[self.filled ..], element);
@ -131,9 +132,11 @@ test "Fixed([]const u8)" {
} }
/// ///
/// Potential errors that may occur while trying to push one or more elements into a stack. /// Potential errors that may occur while trying to push one or more elements into a [Fixed] stack.
/// ///
pub const PushError = io.MakeError; pub const FixedPushError = error {
BufferOverflow,
};
/// ///
/// Creates and returns a [io.Allocator] value wrapping `fixed_stack`. /// Creates and returns a [io.Allocator] value wrapping `fixed_stack`.
@ -154,8 +157,10 @@ pub fn fixedAllocator(fixed_stack: *Fixed(u8)) io.Allocator {
if (buffer_address < stack_address or buffer_address >= if (buffer_address < stack_address or buffer_address >=
(stack_address + stack.filled)) return buffer; (stack_address + stack.filled)) return buffer;
// TODO: Investigate ways of freeing if it is the last allocation. // TODO: Investigate ways of actually freeing if it is the last allocation.
return null; return null;
} else {
// TODO: Investigate ways of in-place relocating if it is the last allocation.
}; };
// Reallocate / allocate the memory. // Reallocate / allocate the memory.
@ -232,7 +237,7 @@ pub fn fixedWriter(fixed_stack: *Fixed(u8)) io.Writer {
return io.Writer.fromClosure(fixed_stack, struct { return io.Writer.fromClosure(fixed_stack, struct {
fn write(stack: *Fixed(u8), buffer: []const u8) usize { fn write(stack: *Fixed(u8), buffer: []const u8) usize {
stack.pushAll(buffer) catch |err| switch (err) { stack.pushAll(buffer) catch |err| switch (err) {
error.OutOfMemory => return 0, error.BufferOverflow => return 0,
}; };
return buffer.len; return buffer.len;

View File

@ -97,7 +97,7 @@ pub fn Hashed(comptime Key: type, comptime Value: type,
/// [InsertError] if it fails. /// [InsertError] if it fails.
/// ///
pub fn insert(self: *Self, key: Key, value: Value) InsertError!void { pub fn insert(self: *Self, key: Key, value: Value) InsertError!void {
if (self.loadFactor() >= self.load_limit) { if (self.isOverloaded()) {
const old_buckets = self.buckets; const old_buckets = self.buckets;
defer io.free(self.allocator, old_buckets); defer io.free(self.allocator, old_buckets);
@ -131,17 +131,18 @@ pub fn Hashed(comptime Key: type, comptime Value: type,
} }
/// ///
/// Returns the current load factor of `self`, which is derived from the number of capacity /// Returns `true` if the current load factor, derived from the number of elements filling
/// that has been filled. /// the bucket table, is greater than the current load limit.
/// ///
pub fn loadFactor(self: Self) f32 { pub fn isOverloaded(self: Self) bool {
return @intToFloat(f32, self.filled) / @intToFloat(f32, self.buckets.len); return (@intToFloat(f32, self.filled) /
@intToFloat(f32, self.buckets.len)) >= self.load_limit;
} }
/// ///
/// Searches for a value indexed with `key` in `self`. /// Searches for a value indexed with `key` in `self`.
/// ///
/// The found value is returned or `null` if an key matching `key` failed to be found. /// The found value is returned or `null` if any key matching `key` failed to be found.
/// ///
pub fn lookup(self: Self, key: Key) ?Value { pub fn lookup(self: Self, key: Key) ?Value {
var bucket = &(self.buckets[@mod(key_context.hash(key), self.buckets.len)]); var bucket = &(self.buckets[@mod(key_context.hash(key), self.buckets.len)]);

View File

@ -3,13 +3,16 @@ const std = @import("std");
const sys = @import("./sys.zig"); const sys = @import("./sys.zig");
/// ///
/// Starts the the game engine. /// Application entry-point.
/// ///
pub fn main() anyerror!void { pub fn main() anyerror!void {
return nosuspend await async sys.display(anyerror, run); return nosuspend await async sys.display(anyerror, runEngine);
} }
fn run(app: *sys.App, graphics: *sys.Graphics) anyerror!void { ///
/// Runs the game engine.
///
fn runEngine(app: *sys.App, graphics: *sys.Graphics) anyerror!void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit(); defer _ = gpa.deinit();

View File

@ -6,7 +6,6 @@ const sys = @import("./sys.zig");
/// ///
const Block = extern struct { const Block = extern struct {
signature: [signature_magic.len]u8 = signature_magic, signature: [signature_magic.len]u8 = signature_magic,
revision: u8 = 0,
path: sys.Path = sys.Path.empty, path: sys.Path = sys.Path.empty,
data_size: u64 = 0, data_size: u64 = 0,
data_head: u64 = 0, data_head: u64 = 0,
@ -15,19 +14,23 @@ const Block = extern struct {
comptime { comptime {
const entry_size = @sizeOf(@This()); const entry_size = @sizeOf(@This());
if (entry_size != 512) @compileError("EntryBlock is greater than 512 bytes"); if (entry_size != 512) @compileError("EntryBlock is not 512 bytes");
} }
}; };
/// ///
/// /// Reference to a file entry in an Oar archive, denoting the starting offset from the top of head
/// of the file and its size.
/// ///
pub const Entry = struct { pub const Entry = struct {
head: u64, head: u64,
size: u64, size: u64,
/// ///
/// [FindError.EntryNotFound] occurs when no entry matched the parameters of the find operation.
/// ///
/// [FindError.ArchiveUnsupported] occurs if the file provided to the find operation is not a
/// valid archive file.
/// ///
pub const FindError = error { pub const FindError = error {
EntryNotFound, EntryNotFound,
@ -35,7 +38,11 @@ pub const Entry = struct {
}; };
/// ///
/// Attempts to perform a binary search on the entry blocks defined in `archive_file` for one
/// matching `entry_path`, returning an [Entry] referencing its data or a [FindError] if it
/// failed.
/// ///
/// **Note** that this operation has `O(log n)` time complexity.
/// ///
pub fn find(archive_file: *sys.ReadableFile, entry_path: sys.Path) FindError!Entry { pub fn find(archive_file: *sys.ReadableFile, entry_path: sys.Path) FindError!Entry {
var header = Header{}; var header = Header{};
@ -78,7 +85,11 @@ pub const Entry = struct {
} }
/// ///
/// Reads the data from `entry` in `archive_file` from the byte at the entry-relative `offset`
/// into `buffer` until either the end of the entry data, end of archive file, or end of buffer
/// is reached.
/// ///
/// The number of bytes read is returned or [sys.FileError] if it failed.
/// ///
pub fn read(entry: Entry, archive_file: *sys.ReadableFile, pub fn read(entry: Entry, archive_file: *sys.ReadableFile,
offset: u64, buffer: []u8) sys.FileError!usize { offset: u64, buffer: []u8) sys.FileError!usize {
@ -89,7 +100,7 @@ pub const Entry = struct {
}; };
/// ///
/// /// Header data that every Oar archive file starts with at byte offset `0`.
/// ///
const Header = extern struct { const Header = extern struct {
signature: [signature_magic.len]u8 = signature_magic, signature: [signature_magic.len]u8 = signature_magic,
@ -101,16 +112,16 @@ const Header = extern struct {
comptime { comptime {
const size = @sizeOf(@This()); const size = @sizeOf(@This());
if (size != 512) @compileError("Header is greater than 512 bytes"); if (size != 512) @compileError("Header is not 512 bytes");
} }
}; };
/// ///
/// /// The magic revision number that this Oar software implementation understands.
/// ///
const revision_magic = 0; const revision_magic = 0;
/// ///
/// Magic identifier used to validate [Entry] data. /// Magic identifier used to validate [Header] and [Block] data.
/// ///
const signature_magic = [3]u8{'o', 'a', 'r'}; const signature_magic = [3]u8{'o', 'a', 'r'};