Skip to content

Commit

Permalink
feat: change options to comptime
Browse files Browse the repository at this point in the history
  • Loading branch information
Hanaasagi committed Jun 24, 2023
1 parent 3a432b0 commit f125d3b
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 131 deletions.
8 changes: 4 additions & 4 deletions src/lib.zig
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@ pub const Options = @import("./loader.zig").Options;
///
/// Where multiple declarations for the same environment variable exist in `.env`
/// file, the *first one* will be applied.
pub fn load(allocator: std.mem.Allocator, options: Options) !void {
pub fn load(allocator: std.mem.Allocator, comptime options: Options) !void {
var finder = FileFinder.default();
const path = try finder.find(allocator);

try loadFrom(allocator, path, options);
}

/// Loads the `.env*` file from the given path.
pub fn loadFrom(allocator: std.mem.Allocator, path: []const u8, options: Options) !void {
/// Loads the `.env` file from the given path.
pub fn loadFrom(allocator: std.mem.Allocator, path: []const u8, comptime options: Options) !void {
var f = try std.fs.cwd().openFile(path, .{});
defer f.close();

var br = std.io.bufferedReader(f.reader());
var reader = br.reader();

var loader = Loader.init(allocator, options);
var loader = Loader(options).init(allocator);
defer loader.deinit();

try loader.load(reader);
Expand Down
254 changes: 127 additions & 127 deletions src/loader.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,151 +24,151 @@ const ParseState = enum {
whitespace,
};

pub const Loader = struct {
allocator: std.mem.Allocator,
parser: parser.LineParser,
options: Options,

const Self = @This();

// --------------------------------------------------------------------------------
// Public API
// --------------------------------------------------------------------------------

pub fn init(allocator: std.mem.Allocator, options: Options) Self {
return Self{
.allocator = allocator,
.parser = parser.LineParser.init(allocator),
.options = options,
};
}
pub fn Loader(comptime options: Options) type {
return struct {
allocator: std.mem.Allocator,
parser: parser.LineParser,

const Self = @This();

// --------------------------------------------------------------------------------
// Public API
// --------------------------------------------------------------------------------

pub fn init(allocator: std.mem.Allocator) Self {
return Self{
.allocator = allocator,
.parser = parser.LineParser.init(allocator),
};
}

pub fn deinit(self: *Self) void {
self.parser.deinit();
}
pub fn deinit(self: *Self) void {
self.parser.deinit();
}

pub fn envs(self: *Self) *const std.StringHashMap(?[]const u8) {
return &self.parser.ctx;
}
pub fn envs(self: *Self) *const std.StringHashMap(?[]const u8) {
return &self.parser.ctx;
}

pub fn load(self: *Self, reader: anytype) !void {
while (true) {
// read a logical line.
const line = try self.readLine(reader);
if (line == null) {
return;
}
pub fn load(self: *Self, reader: anytype) !void {
while (true) {
// read a logical line.
const line = try self.readLine(reader);
if (line == null) {
return;
}

const result = try self.parser.parseLine(line.?);
if (result == null) {
continue;
}
const result = try self.parser.parseLine(line.?);
if (result == null) {
continue;
}

if (self.options.dry_run) {
continue;
}
if (options.dry_run) {
continue;
}

const key = try toCString(result.?.key);
const value = try toCString(result.?.value);
const key = try toCString(result.?.key);
const value = try toCString(result.?.value);

// https://man7.org/linux/man-pages/man3/setenv.3.html
var err_code: c_int = undefined;
if (self.options.override) {
err_code = setenv(&key, &value, 1);
} else {
err_code = setenv(&key, &value, 0);
}
// https://man7.org/linux/man-pages/man3/setenv.3.html
var err_code: c_int = undefined;
if (options.override) {
err_code = setenv(&key, &value, 1);
} else {
err_code = setenv(&key, &value, 0);
}

self.allocator.free(line.?);
self.allocator.free(line.?);

if (err_code != 0) {
switch (err_code) {
22 => return Error.InvalidValue,
12 => return error.OutOfMemory,
else => unreachable,
if (err_code != 0) {
switch (err_code) {
22 => return Error.InvalidValue,
12 => return error.OutOfMemory,
else => unreachable,
}
}
}
}
}

// --------------------------------------------------------------------------------
// Core API
// --------------------------------------------------------------------------------

/// Read a logical line.
/// Multiple lines enclosed in quotation marks are considered as a single line.
/// e.g.
/// ```
/// a = "Line1
/// Line2"
/// ```
/// It will be returned as a single line.
fn readLine(self: Self, reader: anytype) !?[]const u8 {
var cur_state: ParseState = ParseState.complete;
var buf_pos: usize = undefined;
var cur_pos: usize = undefined;

var buf = std.ArrayList(u8).init(self.allocator);
defer buf.deinit();

// TODO: line size
// someone may use JSON text as the value for the env var.
var line_buf: [1024]u8 = undefined;
while (reader.readUntilDelimiterOrEof(&line_buf, '\n')) |data| {
buf_pos = buf.items.len;
if (data == null) {
if (cur_state == .complete) {
return null;
// --------------------------------------------------------------------------------
// Core API
// --------------------------------------------------------------------------------

/// Read a logical line.
/// Multiple lines enclosed in quotation marks are considered as a single line.
/// e.g.
/// ```
/// a = "Line1
/// Line2"
/// ```
/// It will be returned as a single line.
fn readLine(self: Self, reader: anytype) !?[]const u8 {
var cur_state: ParseState = ParseState.complete;
var buf_pos: usize = undefined;
var cur_pos: usize = undefined;

var buf = std.ArrayList(u8).init(self.allocator);
defer buf.deinit();

// TODO: line size
// someone may use JSON text as the value for the env var.
var line_buf: [1024]u8 = undefined;
while (reader.readUntilDelimiterOrEof(&line_buf, '\n')) |data| {
buf_pos = buf.items.len;
if (data == null) {
if (cur_state == .complete) {
return null;
} else {
return Error.ParseError;
}
} else {
return Error.ParseError;
}
} else {
if (data.?.len == 0) {
continue;
}
if (data.?.len == 0) {
continue;
}

try buf.appendSlice(data.?);
// resotre newline
try buf.append('\n');

if (std.mem.startsWith(u8, std.mem.trimLeft(
u8,
buf.items,
// ASCII Whitespace
&[_]u8{ ' ', '\x09', '\x0a', '\x0b', '\x0c', '\x0d' },
), "#")) {
return "";
}
try buf.appendSlice(data.?);
// resotre newline
try buf.append('\n');

if (std.mem.startsWith(u8, std.mem.trimLeft(
u8,
buf.items,
// ASCII Whitespace
&[_]u8{ ' ', '\x09', '\x0a', '\x0b', '\x0c', '\x0d' },
), "#")) {
return "";
}

const result = nextState(cur_state, buf.items[buf_pos..]);
cur_pos = result.new_pos;
cur_state = result.new_state;
const result = nextState(cur_state, buf.items[buf_pos..]);
cur_pos = result.new_pos;
cur_state = result.new_state;

switch (cur_state) {
.complete => {
if (std.mem.endsWith(u8, buf.items, "\n")) {
_ = buf.pop();
if (std.mem.endsWith(u8, buf.items, "\r")) {
switch (cur_state) {
.complete => {
if (std.mem.endsWith(u8, buf.items, "\n")) {
_ = buf.pop();
if (std.mem.endsWith(u8, buf.items, "\r")) {
_ = buf.pop();
}
}
}
return try buf.toOwnedSlice();
},
.comment => {
// truncate
try buf.resize(buf_pos + cur_pos);
return try buf.toOwnedSlice();
},
else => {
// do nothing
},
return try buf.toOwnedSlice();
},
.comment => {
// truncate
try buf.resize(buf_pos + cur_pos);
return try buf.toOwnedSlice();
},
else => {
// do nothing
},
}
}
} else |err| {
return err;
}
} else |err| {
return err;
}
}
};
};
}

fn nextState(prev_state: ParseState, buf: []const u8) struct { new_pos: usize, new_state: ParseState } {
var cur_state = prev_state;
Expand Down Expand Up @@ -237,7 +237,7 @@ test "test load" {
var fbs = std.io.fixedBufferStream(input);
var reader = fbs.reader();

var loader = Loader.init(allocator, .{});
var loader = Loader(.{}).init(allocator);
defer loader.deinit();
try loader.load(reader);

Expand Down Expand Up @@ -266,7 +266,7 @@ test "test multiline" {
var fbs = std.io.fixedBufferStream(input);
var reader = fbs.reader();

var loader = Loader.init(allocator, .{});
var loader = Loader(.{}).init(allocator);
defer loader.deinit();
try loader.load(reader);

Expand All @@ -282,7 +282,7 @@ test "test not override" {
var fbs = std.io.fixedBufferStream(input);
var reader = fbs.reader();

var loader = Loader.init(allocator, .{ .override = false });
var loader = Loader(.{ .override = false }).init(allocator);
defer loader.deinit();
try loader.load(reader);

Expand All @@ -299,7 +299,7 @@ test "test override" {
var fbs = std.io.fixedBufferStream(input);
var reader = fbs.reader();

var loader = Loader.init(allocator, .{ .override = true });
var loader = Loader(.{ .override = true }).init(allocator);
defer loader.deinit();
try loader.load(reader);

Expand Down

0 comments on commit f125d3b

Please sign in to comment.