/ src / libs / utils.zig
utils.zig
  1  const std = @import("std");
  2  const fs = std.fs;
  3  const mem = std.mem;
  4  const os = std.os;
  5  
  6  const RED = "\x1b[38;2;246;96;96m";
  7  const YELLOW = "\x1b[38;2;255;237;129m";
  8  const GREEN = "\x1b[38;2;179;255;114m";
  9  const BLUE = "\x1b[38;2;86;164;255m";
 10  const GRAY = "\x1b[38;2;57;62;65m";
 11  const DEFAULT = "\x1b[0m";
 12  const MAX_KEY_LEN = 50;
 13  const whitespaces = [_]u8{ ' ', '\t' };
 14  
 15  fn baseLogger(comptime color: []const u8, comptime label: []const u8, comptime fmt: []const u8, args: anytype) !void {
 16      const timestamp: u64 = @truncate(@abs(std.time.timestamp()));
 17      var stdout = std.io.getStdOut();
 18  
 19      try std.fmt.format(stdout.writer(), "{s}[{any}:{any}:{any}]{s} {s}{s}{s} \t-- " ++ fmt ++ "\n", .{
 20          GRAY,
 21          @as(u5, @truncate((timestamp / 3600) % 24)),
 22          @as(u6, @truncate((timestamp / 60) % 60)),
 23          @as(u6, @truncate(timestamp % 60)),
 24          DEFAULT,
 25          color,
 26          label,
 27          DEFAULT,
 28      } ++ args);
 29  }
 30  
 31  pub fn info(comptime fmt: []const u8, args: anytype) !void {
 32      try baseLogger(BLUE, "INFO", fmt, args);
 33  }
 34  
 35  pub fn warn(comptime fmt: []const u8, args: anytype) !void {
 36      try baseLogger(YELLOW, "WARN", fmt, args);
 37  }
 38  
 39  pub fn err(comptime fmt: []const u8, args: anytype) !void {
 40      try baseLogger(RED, "ERROR", fmt, args);
 41  }
 42  
 43  pub fn success(comptime fmt: []const u8, args: anytype) !void {
 44      try baseLogger(GREEN, "SUCESS", fmt, args);
 45  }
 46  
 47  pub fn parseKVPair(reader: anytype, key: []const u8, buffer: []u8, delimiter: u8) !?[]const u8 {
 48      var valuebuffer_stream = std.io.fixedBufferStream(buffer);
 49      const value_writer = valuebuffer_stream.writer();
 50  
 51      var keybuffer: [MAX_KEY_LEN]u8 = undefined;
 52      var keybuffer_stream = std.io.fixedBufferStream(&keybuffer);
 53      var key_writer = keybuffer_stream.writer();
 54  
 55      while (reader.readByte()) |byte| {
 56          if (byte == '\t') continue;
 57          if (byte == delimiter) {
 58              if (mem.eql(u8, key, keybuffer_stream.getWritten())) {
 59                  // Note : We could write our own implementation of streamUntilDelimiter to account for whitespaces,
 60                  // trimming the spaces in one go
 61                  reader.streamUntilDelimiter(value_writer, '\n', buffer.len) catch |e| {
 62                      err("parseKVPair :  {s}", .{@errorName(e)}) catch {};
 63                      break;
 64                  };
 65                  return mem.trim(u8, valuebuffer_stream.getWritten(), " ");
 66              }
 67              keybuffer_stream.reset();
 68              try reader.skipUntilDelimiterOrEof('\n');
 69              continue;
 70          }
 71  
 72          try key_writer.writeByte(byte);
 73      } else |e| {
 74          err("Key not found: {s} ({s})", .{ key, @errorName(e) }) catch {};
 75  
 76          return null;
 77      }
 78      unreachable;
 79  }
 80  
 81  pub fn parseKVPairOpenFile(path: []const u8, key: []const u8, buffer: []u8, delimiter: u8) !?[]const u8 {
 82      var file_descriptor = try fs.openFileAbsolute(path, .{ .intended_io_mode = .blocking });
 83      defer file_descriptor.close();
 84  
 85      return parseKVPair(file_descriptor.reader(), key, buffer, delimiter);
 86  }
 87  
 88  pub fn getenv(name: []const u8, buffer: []u8) ?[]const u8 {
 89      var file_descriptor = std.fs.cwd().openFile(".env", .{}) catch |e| {
 90          switch (e) {
 91              error.FileNotFound => {
 92                  warn("Unable to find .env in current working directory, resorting to environment variable !", .{}) catch {};
 93              },
 94              error.AccessDenied => {
 95                  warn("Missing read permission for .env file, resorting to environment variable !", .{}) catch {};
 96              },
 97              else => {},
 98          }
 99          return os.getenv(name);
100      };
101      defer file_descriptor.close();
102      return parseKVPair(file_descriptor.reader(), name, buffer, '=') catch null;
103  }