prefect server in zig
at main 53 lines 1.9 kB view raw
1const std = @import("std"); 2 3/// base64 encode a byte slice 4pub fn base64Encode(alloc: std.mem.Allocator, data: []const u8) ![]const u8 { 5 const encoder = std.base64.standard.Encoder; 6 const size = encoder.calcSize(data.len); 7 const buf = try alloc.alloc(u8, size); 8 return encoder.encode(buf, data); 9} 10 11/// base64 decode a string 12pub fn base64Decode(alloc: std.mem.Allocator, encoded: []const u8) ![]const u8 { 13 const decoder = std.base64.standard.Decoder; 14 // upper bound: 3 bytes per 4 chars 15 const max_size = (encoded.len / 4 + 1) * 3; 16 const buf = try alloc.alloc(u8, max_size); 17 decoder.decode(buf, encoded) catch return error.InvalidBase64; 18 // calculate actual decoded length (may be less due to padding) 19 const actual_len = encoded.len / 4 * 3 - countPadding(encoded); 20 return buf[0..actual_len]; 21} 22 23fn countPadding(encoded: []const u8) usize { 24 var padding: usize = 0; 25 if (encoded.len > 0 and encoded[encoded.len - 1] == '=') padding += 1; 26 if (encoded.len > 1 and encoded[encoded.len - 2] == '=') padding += 1; 27 return padding; 28} 29 30/// URL decode a percent-encoded string (handles %XX and + for space) 31pub fn urlDecode(alloc: std.mem.Allocator, encoded: []const u8) ![]const u8 { 32 var result = std.ArrayListUnmanaged(u8){}; 33 var i: usize = 0; 34 while (i < encoded.len) { 35 if (encoded[i] == '%' and i + 2 < encoded.len) { 36 const hex = encoded[i + 1 .. i + 3]; 37 const byte = std.fmt.parseInt(u8, hex, 16) catch { 38 try result.append(alloc, encoded[i]); 39 i += 1; 40 continue; 41 }; 42 try result.append(alloc, byte); 43 i += 3; 44 } else if (encoded[i] == '+') { 45 try result.append(alloc, ' '); 46 i += 1; 47 } else { 48 try result.append(alloc, encoded[i]); 49 i += 1; 50 } 51 } 52 return result.toOwnedSlice(alloc); 53}