Skip to content

Commit

Permalink
fix memory leaks and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nektro committed Jan 9, 2025
1 parent 3d0ddb0 commit 91e138c
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 1 deletion.
13 changes: 13 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const std = @import("std");
const deps = @import("./deps.zig");

pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
Expand Down Expand Up @@ -36,4 +37,16 @@ pub fn build(b: *std.Build) void {

const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);

const tests = b.addTest(.{
.root_source_file = b.path("test.zig"),
.target = target,
.optimize = mode,
});
deps.addAllTo(tests);

const test_step = b.step("test", "Run all library tests");
const tests_run = b.addRunArtifact(tests);
tests_run.has_side_effects = true;
test_step.dependOn(&tests_run.step);
}
1 change: 1 addition & 0 deletions licenses.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
MIT:
= https://spdx.org/licenses/MIT
- This
- git https://github.com/nektro/zig-expect
22 changes: 22 additions & 0 deletions src/lib.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@ pub const Value = union(enum) {
List: []const Value,
Dictionary: std.StringArrayHashMapUnmanaged(Value),

pub fn deinit(self: *const Value, alloc: std.mem.Allocator) void {
switch (self.*) {
.String => |s| alloc.free(s),
.Integer => {},
.List => |l| {
for (l) |*v| v.deinit(alloc);
alloc.free(l);
},
.Dictionary => |*d| {
for (d.keys()) |k| alloc.free(k);
for (d.values()) |*v| v.deinit(alloc);
@constCast(d).deinit(alloc);
},
}
}

pub fn format(self: Value, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) @TypeOf(writer).Error!void {
_ = fmt;
_ = options;
Expand Down Expand Up @@ -129,6 +145,7 @@ fn parseInner(pr: anytype, alloc: std.mem.Allocator) anyerror!Value {

fn parseString(pr: anytype, alloc: std.mem.Allocator) ![]const u8 {
const str = try pr.reader().readUntilDelimiterAlloc(alloc, ':', max_number_length);
defer alloc.free(str);
const len = try std.fmt.parseInt(usize, str, 10);
var buf = try alloc.alloc(u8, len);
const l = try pr.reader().readAll(buf);
Expand All @@ -137,12 +154,14 @@ fn parseString(pr: anytype, alloc: std.mem.Allocator) ![]const u8 {

fn parseInteger(pr: anytype, alloc: std.mem.Allocator) !i64 {
const str = try pr.reader().readUntilDelimiterAlloc(alloc, 'e', max_number_length);
defer alloc.free(str);
const x = try std.fmt.parseInt(i64, str, 10);
return x;
}

fn parseList(pr: anytype, alloc: std.mem.Allocator) ![]Value {
var list = std.ArrayList(Value).init(alloc);
errdefer list.deinit();
while (true) {
if (try pr.peek()) |c| {
if (c == 'e') {
Expand All @@ -160,6 +179,9 @@ fn parseList(pr: anytype, alloc: std.mem.Allocator) ![]Value {

fn parseDict(pr: anytype, alloc: std.mem.Allocator) !std.StringArrayHashMapUnmanaged(Value) {
var map = std.StringArrayHashMapUnmanaged(Value){};
errdefer map.deinit(alloc);
errdefer for (map.keys()) |k| alloc.free(k);
errdefer for (map.values()) |v| v.deinit(alloc);
while (true) {
if (try pr.peek()) |c| {
if (c == 'e') {
Expand Down
22 changes: 22 additions & 0 deletions test.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const std = @import("std");
const bencode = @import("bencode");
const expect = @import("expect").expect;

test {
const alloc = std.testing.allocator;
const file = @embedFile("./archlinux-2021.04.01-x86_64.iso.torrent");

var fbs = std.io.fixedBufferStream(file);
const r = fbs.reader();
const ben = try bencode.parse(r, alloc);
defer ben.deinit(alloc);

try expect(ben.getS("comment")).toEqualString("Arch Linux 2021.04.01 (www.archlinux.org)");
try expect(ben.getS("created by")).toEqualString("mktorrent 1.1");
try expect(ben.getU("creation date")).toEqual(1617297570);
try expect(ben.getD("info")).not().toBeNull();
try expect(ben.getD("info").?.getU("length")).toEqual(786771968);
try expect(ben.getD("info").?.getS("name")).toEqualString("archlinux-2021.04.01-x86_64.iso");
try expect(ben.getD("info").?.getU("piece length")).toEqual(524288);
try expect(ben.getD("info").?.getS("pieces").?.len).toEqual(30020);
}
3 changes: 2 additions & 1 deletion zig.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ id: vwvoz97vjt4bjlyr6jdftzcuv6huc8ynjp4i7bjmqkdkt0hh
name: bencode
main: src/lib.zig
license: MIT
dependencies:
root_dependencies:
- src: git https://github.com/nektro/zig-expect

0 comments on commit 91e138c

Please sign in to comment.