const std = @import("std"); //////////////////////////////////////////////////////// // The following data structure has a bunch of aliased // data types specifically so it's easier to understand // for people with no experience in Zig, and perhaps // little to no experience programming. // // Please avoid complicated terminology unless it is // fully necessary. //////////////////////////////////////////////////////// pub const Tag = struct { name: []const u8, posts: []Post, }; pub const Time = struct { raw: Integer, year: Integer, month: TwoDigits, day: TwoDigits, hour: TwoDigits, minute: TwoDigits, second: TwoDigits, }; pub const Post = struct { id: Id = 0, is_secret: bool, title: String, description: String, author: String, // kebab-case list of tags tags: []const String, source: Path, url: Path, created: Time, updated: Time, body: ?String, }; website: struct { title: String, description: String, url: String, feeds: struct { html: ?Path = null, rss: ?Path = null, atom: ?Path = null, }, }, pass: struct { feed_template: Hash, post_template: Hash, }, // JSON Map of custom values custom: Value, // Only valid when processing individual posts post: ?Post = null, // Only valid when processing feeds. posts: ?[]Post = null, tags: []Tag, // Map of tag name to list of posts by_tag: Value, //////////////////////////////////////////////////////// //////////////////////////////////////////////////////// //////////////////////////////////////////////////////// ///////////// IMPLEMENTATION DETAILS /////////////////// const String = []const u8; const Path = String; const Integer = i64; const Float = f64; const ArbitraryData = std.json.Value; const Value = std.json.Value; const TwoDigits = [2]u8; pub const empty_time = std.mem.zeroes(Time); pub const Hash = Integer; pub const Id = Integer; const helper = @import("helper.zig"); // TODO: Zig MUST have a function for this!!!! fn formatTwoDigits(n: u8) [2]u8 { return if (n < 10) [_]u8{ '0', '0' + n } else [_]u8{ '0' + @as(u8, @intCast(n / 10)), '0' + @as(u8, @intCast(n % 10)), }; } pub fn timeFromTimestamp(now: i64) Time { const Datetime = @import("datetime").datetime.Datetime; var time: Time = undefined; const e = Datetime.fromTimestamp(now); time.raw = now; time.year = @intCast(e.date.year); time.month = formatTwoDigits(e.date.month); time.day = formatTwoDigits(e.date.day); time.hour = formatTwoDigits(e.time.hour); time.minute = formatTwoDigits(e.time.minute); time.second = formatTwoDigits(e.time.second); return time; } pub fn copyPost(post: Post, allocator: std.mem.Allocator) !Post { return Post{ .id = post.id, .is_secret = post.is_secret, .title = try allocator.dupe(u8, post.title), .description = try allocator.dupe(u8, post.description), .author = try allocator.dupe(u8, post.author), .tags = try helper.copyStringList(allocator, post.tags), .source = try allocator.dupe(u8, post.source), // Relative to source path .url = try allocator.dupe(u8, post.url), // Relative to output path .created = post.created, .updated = post.updated, .body = if (post.body) |body| try allocator.dupe(u8, body) else null, }; } pub fn freePost(post: Post, allocator: std.mem.Allocator) void { allocator.free(post.title); allocator.free(post.description); allocator.free(post.author); helper.freeStringList(allocator, post.tags); allocator.free(post.source); allocator.free(post.url); if (post.body) |body| allocator.free(body); }