zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

utils.zig (3827B) - Raw


      1 const std = @import("std");
      2 const builtin = @import("builtin");
      3 
      4 /// Like std.io.FixedBufferStream but does no bounds checking
      5 pub const UncheckedSliceWriter = struct {
      6     const Self = @This();
      7 
      8     pos: usize = 0,
      9     slice: []u8,
     10 
     11     pub fn write(self: *Self, char: u8) void {
     12         self.slice[self.pos] = char;
     13         self.pos += 1;
     14     }
     15 
     16     pub fn writeSlice(self: *Self, slice: []const u8) void {
     17         for (slice) |c| {
     18             self.write(c);
     19         }
     20     }
     21 
     22     pub fn getWritten(self: Self) []u8 {
     23         return self.slice[0..self.pos];
     24     }
     25 };
     26 
     27 /// Cross-platform 'std.fs.Dir.openFile' wrapper that will always return IsDir if
     28 /// a directory is attempted to be opened.
     29 /// TODO: Remove once https://github.com/ziglang/zig/issues/5732 is addressed.
     30 pub fn openFileNotDir(cwd: std.fs.Dir, path: []const u8, flags: std.fs.File.OpenFlags) std.fs.File.OpenError!std.fs.File {
     31     const file = try cwd.openFile(path, flags);
     32     errdefer file.close();
     33     // https://github.com/ziglang/zig/issues/5732
     34     if (builtin.os.tag != .windows) {
     35         const stat = try file.stat();
     36 
     37         if (stat.kind == .directory)
     38             return error.IsDir;
     39     }
     40     return file;
     41 }
     42 
     43 /// Emulates the Windows implementation of `iswdigit`, but only returns true
     44 /// for the non-ASCII digits that `iswdigit` on Windows would return true for.
     45 pub fn isNonAsciiDigit(c: u21) bool {
     46     return switch (c) {
     47         '²',
     48         '³',
     49         '¹',
     50         '\u{660}'...'\u{669}',
     51         '\u{6F0}'...'\u{6F9}',
     52         '\u{7C0}'...'\u{7C9}',
     53         '\u{966}'...'\u{96F}',
     54         '\u{9E6}'...'\u{9EF}',
     55         '\u{A66}'...'\u{A6F}',
     56         '\u{AE6}'...'\u{AEF}',
     57         '\u{B66}'...'\u{B6F}',
     58         '\u{BE6}'...'\u{BEF}',
     59         '\u{C66}'...'\u{C6F}',
     60         '\u{CE6}'...'\u{CEF}',
     61         '\u{D66}'...'\u{D6F}',
     62         '\u{E50}'...'\u{E59}',
     63         '\u{ED0}'...'\u{ED9}',
     64         '\u{F20}'...'\u{F29}',
     65         '\u{1040}'...'\u{1049}',
     66         '\u{1090}'...'\u{1099}',
     67         '\u{17E0}'...'\u{17E9}',
     68         '\u{1810}'...'\u{1819}',
     69         '\u{1946}'...'\u{194F}',
     70         '\u{19D0}'...'\u{19D9}',
     71         '\u{1B50}'...'\u{1B59}',
     72         '\u{1BB0}'...'\u{1BB9}',
     73         '\u{1C40}'...'\u{1C49}',
     74         '\u{1C50}'...'\u{1C59}',
     75         '\u{A620}'...'\u{A629}',
     76         '\u{A8D0}'...'\u{A8D9}',
     77         '\u{A900}'...'\u{A909}',
     78         '\u{AA50}'...'\u{AA59}',
     79         '\u{FF10}'...'\u{FF19}',
     80         => true,
     81         else => false,
     82     };
     83 }
     84 
     85 pub const ErrorMessageType = enum { err, warning, note };
     86 
     87 /// Used for generic colored errors/warnings/notes, more context-specific error messages
     88 /// are handled elsewhere.
     89 pub fn renderErrorMessage(writer: *std.io.Writer, config: std.io.tty.Config, msg_type: ErrorMessageType, comptime format: []const u8, args: anytype) !void {
     90     switch (msg_type) {
     91         .err => {
     92             try config.setColor(writer, .bold);
     93             try config.setColor(writer, .red);
     94             try writer.writeAll("error: ");
     95         },
     96         .warning => {
     97             try config.setColor(writer, .bold);
     98             try config.setColor(writer, .yellow);
     99             try writer.writeAll("warning: ");
    100         },
    101         .note => {
    102             try config.setColor(writer, .reset);
    103             try config.setColor(writer, .cyan);
    104             try writer.writeAll("note: ");
    105         },
    106     }
    107     try config.setColor(writer, .reset);
    108     if (msg_type == .err) {
    109         try config.setColor(writer, .bold);
    110     }
    111     try writer.print(format, args);
    112     try writer.writeByte('\n');
    113     try config.setColor(writer, .reset);
    114 }
    115 
    116 pub fn isLineEndingPair(first: u8, second: u8) bool {
    117     if (first != '\r' and first != '\n') return false;
    118     if (second != '\r' and second != '\n') return false;
    119 
    120     // can't be \n\n or \r\r
    121     if (first == second) return false;
    122 
    123     return true;
    124 }