From 7eff166e1f7b440392be1082e3edd0c38b92d77c Mon Sep 17 00:00:00 2001 From: Martin Ashby Date: Sat, 11 Nov 2023 11:20:15 +0000 Subject: Add basic meta info file parsing --- src/metainfo.zig | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/metainfo.zig (limited to 'src/metainfo.zig') diff --git a/src/metainfo.zig b/src/metainfo.zig new file mode 100644 index 0000000..9fa4788 --- /dev/null +++ b/src/metainfo.zig @@ -0,0 +1,47 @@ +//! https://wiki.theory.org/BitTorrentSpecification#Metainfo_File_Structure +const std = @import("std"); +const bencode = @import("bencode.zig"); +const MetaInfo = @This(); + +pub const Info = struct { + pub const File = struct { + name: []const u8, + length: u64, + path: []const u8, + }; + piece_length: u64, + pieces: []const u8, + files: []File, + pub fn parse(b: bencode.BValue) !Info { + var d = b.asDict() catch return error.Malformatted; + const pl = d.get("piece length") orelse return error.Malformatted; + const pp = d.get("pieces") orelse return error.Malformatted; + return .{ + .piece_length = pl.asInt(u64) catch return error.Malformatted, + .pieces = pp.asString() catch return error.Malformatted, + .files = &[_]File{}, + }; + } +}; + +info: Info, +announce: []const u8, + +pub fn parse(b: bencode.BValue) !MetaInfo { + var d = b.asDict() catch return error.Malformatted; + const i = d.get("info") orelse return error.Malformatted; + const a = d.get("announce") orelse return error.Malformatted; + return .{ + .info = try Info.parse(i), + .announce = a.asString() catch return error.Malformatted, + }; +} + +test "sample" { + const a = std.testing.allocator; + const sample_str = @embedFile("sample.torrent"); + var b = try bencode.bdecodeBuf(a, sample_str); + defer b.deinit(a); + const mi = try MetaInfo.parse(b); + try std.testing.expectEqualStrings("http://bittorrent-test-tracker.codecrafters.io/announce", mi.announce); +} -- cgit v1.2.3-ZIG