Skip to content

Commit

Permalink
Ability to load raw arrays (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
pwbh authored Sep 3, 2024
1 parent 9f2176d commit 52b22eb
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 75 deletions.
75 changes: 71 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ pub fn build(b: *std.Build) void {
}
```

Now in your code you may import and use ymlz, I will be loading the following YAML file located in the root of my project under the name `file.yml`:
### Parsing YAML from file

We can utilize `loadFile` which expects the absolute path to your YAML file, I will be loading the following YAML file located in the root of my project under the name `file.yml`:

```yml
first: 500
Expand All @@ -63,9 +65,11 @@ inner:
stringed: its just a string
```
In your Zig codebase:
main.zig:
```zig
/// Usage
/// zig build run -- ./file.yml
const std = @import("std");

const Ymlz = @import("ymlz").Ymlz;
Expand All @@ -88,8 +92,7 @@ const Tester = struct {
},
},
};
/// Usage
/// zig build run -- ./file.yml

pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
Expand Down Expand Up @@ -126,6 +129,70 @@ pub fn main() !void {
}
```

### Parsing YAML from bytes

Parsing YAML file using generic u8 slice for the sake of example lets parse a small YAML inlined in a to some varaible that contains our YAML u8 slice.

```zig
const std = @import("std");
const Ymlz = @import("root.zig").Ymlz;
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer _ = gpa.deinit();
const yaml_content =
\\first: 500
\\second: -3
\\name: just testing strings overhere # just a comment
\\fourth: 142.241
\\# comment in between lines
\\foods:
\\ - Apple
\\ - Orange
\\ - Strawberry
\\ - Mango
\\inner:
\\ abcd: 12
\\ k: 2
\\ l: hello world # comment somewhere
\\ another:
\\ new: 1
\\ stringed: its just a string
;
const Experiment = struct {
first: i32,
second: i64,
name: []const u8,
fourth: f32,
foods: [][]const u8,
inner: struct {
abcd: i32,
k: u8,
l: []const u8,
another: struct {
new: f32,
stringed: []const u8,
},
},
};
var ymlz = try Ymlz(Experiment).init(allocator);
const result = try ymlz.loadRaw(yaml_content);
defer ymlz.deinit(result);
std.debug.print("Experiment.first: {}\n", .{result.first});
}
```

### Parsing by providing a custom std.io.AnyReader

It's possible to pass your own implementation of the std.io.AnyReader interface to ymlz using `loadReader` which is used internally for both `loadFile` and `loadRaw`. See [internal implementation](https://github.com/pwbh/ymlz/blob/master/src/root.zig#L64) for reference.

## Contribution

You are more then welcomed to submit a PR, ymlz codebase is still pretty small and it should be relatively simple to get into it, if you have any questions regarding the project or you just need assist starting out, open an issue.
Expand Down
109 changes: 38 additions & 71 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,84 +2,51 @@ const std = @import("std");

const Ymlz = @import("root.zig").Ymlz;

const Image = struct {
slot: u64,
name: []const u8,
multisampled: bool,
type: []const u8,
sample_type: []const u8,
};

const Uniform = struct {
name: []const u8,
type: []const u8,
array_count: i32,
offset: usize,
};

const UniformBlock = struct {
slot: u64,
size: u64,
struct_name: []const u8,
inst_name: []const u8,
uniforms: []Uniform,
};

const Input = struct {
slot: u64,
name: []const u8,
sem_name: []const u8,
sem_index: usize,
};

const Details = struct {
path: []const u8,
is_binary: bool,
entry_point: []const u8,
inputs: []Input,
outputs: []Input,
uniform_blocks: []UniformBlock,
images: ?[]Image,
};

const Program = struct {
name: []const u8,
vs: Details,
fs: Details,
};

const Shader = struct {
slang: []const u8,
programs: []Program,
};

const Experiment = struct {
shaders: []Shader,
};

pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer _ = gpa.deinit();

const args = try std.process.argsAlloc(allocator);
defer std.process.argsFree(allocator, args);

if (args.len < 2) {
return error.NoPathArgument;
}

const yml_location = args[1];

const yml_path = try std.fs.cwd().realpathAlloc(
allocator,
yml_location,
);
defer allocator.free(yml_path);
const yaml_content =
\\first: 500
\\second: -3
\\name: just testing strings overhere # just a comment
\\fourth: 142.241
\\# comment in between lines
\\foods:
\\ - Apple
\\ - Orange
\\ - Strawberry
\\ - Mango
\\inner:
\\ abcd: 12
\\ k: 2
\\ l: hello world # comment somewhere
\\ another:
\\ new: 1
\\ stringed: its just a string
;

const Experiment = struct {
first: i32,
second: i64,
name: []const u8,
fourth: f32,
foods: [][]const u8,
inner: struct {
abcd: i32,
k: u8,
l: []const u8,
another: struct {
new: f32,
stringed: []const u8,
},
},
};

var ymlz = try Ymlz(Experiment).init(allocator);
const result = try ymlz.loadFile(yml_path);
const result = try ymlz.loadRaw(yaml_content);
defer ymlz.deinit(result);

std.debug.print("Tester: {s}\n", .{result.shaders[0].programs[0].fs.uniform_blocks[0].uniforms[0].name});
std.debug.print("Experiment.first: {}\n", .{result.first});
}
17 changes: 17 additions & 0 deletions src/root.zig
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ pub fn Ymlz(comptime Destination: type) type {

const Self = @This();

const InternalRawContenxt = struct { current_index: usize = 0, buf: []const u8 };

pub fn init(allocator: Allocator) !Self {
return .{
.allocator = allocator,
Expand Down Expand Up @@ -74,6 +76,21 @@ pub fn Ymlz(comptime Destination: type) type {
return std.fs.File.read(file.*, buf);
}

pub fn loadRaw(self: *Self, raw: []const u8) !Destination {
const context: InternalRawContenxt = .{ .buf = raw };
const any_reader: std.io.AnyReader = .{ .context = &context, .readFn = rawRead };
return self.loadReader(any_reader);
}

fn rawRead(context: *const anyopaque, buf: []u8) anyerror!usize {
var internal_raw_context: *InternalRawContenxt = @constCast(@alignCast(@ptrCast(context)));
const source = internal_raw_context.buf[internal_raw_context.current_index..];
const len = @min(buf.len, source.len);
@memcpy(buf[0..len], source[0..len]);
internal_raw_context.current_index += len;
return len;
}

/// Allows passing a reader which will be used to parse your raw yml bytes.
pub fn loadReader(self: *Self, reader: AnyReader) !Destination {
if (@typeInfo(Destination) != .Struct) {
Expand Down

0 comments on commit 52b22eb

Please sign in to comment.