diff --git a/bench/src/reader.zig b/bench/src/reader.zig
index 34d60d1..8a82fbb 100644
--- a/bench/src/reader.zig
+++ b/bench/src/reader.zig
@@ -5,7 +5,9 @@ pub const main = @import("common.zig").main;
pub fn runBench(data: []const u8) !void {
var data_stream = std.io.fixedBufferStream(data);
- var reader = xml.reader(std.heap.c_allocator, data_stream.reader(), xml.encoding.Utf8Decoder{}, .{});
+ var reader = xml.reader(std.heap.c_allocator, data_stream.reader(), .{
+ .DecoderType = xml.encoding.Utf8Decoder,
+ });
defer reader.deinit();
while (try reader.next()) |_| {}
}
diff --git a/bench/src/token_reader.zig b/bench/src/token_reader.zig
index 13868ed..2190008 100644
--- a/bench/src/token_reader.zig
+++ b/bench/src/token_reader.zig
@@ -5,6 +5,8 @@ pub const main = @import("common.zig").main;
pub fn runBench(data: []const u8) !void {
var data_stream = std.io.fixedBufferStream(data);
- var token_reader = xml.tokenReader(data_stream.reader(), xml.encoding.Utf8Decoder{}, .{});
+ var token_reader = xml.tokenReader(data_stream.reader(), .{
+ .DecoderType = xml.encoding.Utf8Decoder,
+ });
while (try token_reader.next()) |_| {}
}
diff --git a/examples/read.zig b/examples/read.zig
index 7102a50..3fb77f3 100644
--- a/examples/read.zig
+++ b/examples/read.zig
@@ -20,7 +20,7 @@ pub fn main() !void {
const input_file = try std.fs.cwd().openFile(input_path, .{});
defer input_file.close();
var input_buffered_reader = std.io.bufferedReader(input_file.reader());
- var reader = xml.reader(allocator, input_buffered_reader.reader(), xml.encoding.DefaultDecoder{}, .{});
+ var reader = xml.reader(allocator, input_buffered_reader.reader(), .{});
defer reader.deinit();
while (try reader.next()) |event| {
diff --git a/src/reader.zig b/src/reader.zig
index 5906b06..4eb7f77 100644
--- a/src/reader.zig
+++ b/src/reader.zig
@@ -294,10 +294,9 @@ pub const NoOpNamespaceContext = struct {
pub fn reader(
allocator: Allocator,
r: anytype,
- decoder: anytype,
comptime options: ReaderOptions,
-) Reader(@TypeOf(r), @TypeOf(decoder), options) {
- return Reader(@TypeOf(r), @TypeOf(decoder), options).init(allocator, r, decoder);
+) Reader(@TypeOf(r), options) {
+ return Reader(@TypeOf(r), options).init(allocator, r, .{});
}
/// Reads a full XML document from a `std.io.Reader`.
@@ -354,6 +353,8 @@ pub fn readDocument(
/// Options for a `Reader`.
pub const ReaderOptions = struct {
+ /// The type of decoder to use.
+ DecoderType: type = encoding.DefaultDecoder,
/// The size of the internal buffer.
///
/// This limits the byte length of "non-splittable" content, such as
@@ -390,11 +391,7 @@ pub const ReaderOptions = struct {
/// Since this parser wraps a `TokenReader`, the caveats on the `buffer_size`
/// bounding the length of "non-splittable" content which are outlined in its
/// documentation apply here as well.
-pub fn Reader(
- comptime ReaderType: type,
- comptime DecoderType: type,
- comptime options: ReaderOptions,
-) type {
+pub fn Reader(comptime ReaderType: type, comptime options: ReaderOptions) type {
return struct {
token_reader: TokenReaderType,
/// A stack of element names enclosing the current context.
@@ -422,7 +419,8 @@ pub fn Reader(
allocator: Allocator,
const Self = @This();
- const TokenReaderType = TokenReader(ReaderType, DecoderType, .{
+ const TokenReaderType = TokenReader(ReaderType, .{
+ .DecoderType = options.DecoderType,
.buffer_size = options.buffer_size,
.enable_normalization = options.enable_normalization,
.track_location = options.track_location,
@@ -439,7 +437,7 @@ pub fn Reader(
QNameNotAllowed,
} || Allocator.Error || TokenReaderType.Error;
- pub fn init(allocator: Allocator, r: ReaderType, decoder: DecoderType) Self {
+ pub fn init(allocator: Allocator, r: ReaderType, decoder: options.DecoderType) Self {
return .{
.token_reader = TokenReaderType.init(r, decoder),
.event_arena = ArenaAllocator.init(allocator),
@@ -916,7 +914,7 @@ test "namespace handling" {
fn testValid(comptime options: ReaderOptions, input: []const u8, expected_events: []const Event) !void {
var input_stream = std.io.fixedBufferStream(input);
- var input_reader = reader(testing.allocator, input_stream.reader(), encoding.Utf8Decoder{}, options);
+ var input_reader = reader(testing.allocator, input_stream.reader(), options);
defer input_reader.deinit();
var i: usize = 0;
while (try input_reader.next()) |event| : (i += 1) {
@@ -937,7 +935,7 @@ fn testValid(comptime options: ReaderOptions, input: []const u8, expected_events
fn testInvalid(comptime options: ReaderOptions, input: []const u8, expected_error: anyerror) !void {
var input_stream = std.io.fixedBufferStream(input);
- var input_reader = reader(testing.allocator, input_stream.reader(), encoding.Utf8Decoder{}, options);
+ var input_reader = reader(testing.allocator, input_stream.reader(), options);
defer input_reader.deinit();
while (input_reader.next()) |_| {} else |err| {
try testing.expectEqual(expected_error, err);
@@ -966,7 +964,7 @@ test "nextNode" {
\\
\\
);
- var input_reader = reader(testing.allocator, input_stream.reader(), encoding.Utf8Decoder{}, .{});
+ var input_reader = reader(testing.allocator, input_stream.reader(), .{});
defer input_reader.deinit();
try testing.expectEqualDeep(@as(?Event, .{ .xml_declaration = .{ .version = "1.0" } }), try input_reader.next());
@@ -1015,7 +1013,7 @@ test "nextNode namespace handling" {
\\
\\
);
- var input_reader = reader(testing.allocator, input_stream.reader(), encoding.Utf8Decoder{}, .{});
+ var input_reader = reader(testing.allocator, input_stream.reader(), .{});
defer input_reader.deinit();
var root_start = try input_reader.next();
@@ -1065,7 +1063,7 @@ test readDocument {
\\
\\
);
- var document_node = try readDocument(testing.allocator, input_stream.reader(), encoding.Utf8Decoder{}, .{});
+ var document_node = try readDocument(testing.allocator, input_stream.reader(), .{});
defer document_node.deinit();
try testing.expectEqualDeep(Node.Document{ .version = "1.0", .children = &.{
@@ -1103,7 +1101,7 @@ test Children {
\\
\\
);
- var input_reader = reader(testing.allocator, input_stream.reader(), encoding.Utf8Decoder{}, .{});
+ var input_reader = reader(testing.allocator, input_stream.reader(), .{});
defer input_reader.deinit();
try testing.expectEqualDeep(@as(?Event, .{ .element_start = .{ .name = .{ .local = "root" } } }), try input_reader.next());
@@ -1135,7 +1133,7 @@ test "skip children" {
\\
\\
);
- var input_reader = reader(testing.allocator, input_stream.reader(), encoding.Utf8Decoder{}, .{});
+ var input_reader = reader(testing.allocator, input_stream.reader(), .{});
defer input_reader.deinit();
try testing.expectEqualDeep(@as(?Event, .{ .element_start = .{ .name = .{ .local = "root" } } }), try input_reader.next());
diff --git a/src/token_reader.zig b/src/token_reader.zig
index d3601c6..25cda3f 100644
--- a/src/token_reader.zig
+++ b/src/token_reader.zig
@@ -158,14 +158,15 @@ pub const NoOpLocation = struct {
/// (4096).
pub fn tokenReader(
reader: anytype,
- decoder: anytype,
comptime options: TokenReaderOptions,
-) TokenReader(@TypeOf(reader), @TypeOf(decoder), options) {
- return TokenReader(@TypeOf(reader), @TypeOf(decoder), options).init(reader, decoder);
+) TokenReader(@TypeOf(reader), options) {
+ return TokenReader(@TypeOf(reader), options).init(reader, .{});
}
/// Options for a `TokenReader`.
pub const TokenReaderOptions = struct {
+ /// The type of decoder to use.
+ DecoderType: type = encoding.DefaultDecoder,
/// The size of the internal buffer.
///
/// This limits the byte length of "non-splittable" content, such as
@@ -204,15 +205,11 @@ pub const TokenReaderOptions = struct {
/// important. Additionally, `buffer_size` limits the maximum byte length of
/// "unsplittable" content, such as element and attribute names (but not
/// "splittable" content, such as element text content and attribute values).
-pub fn TokenReader(
- comptime ReaderType: type,
- comptime DecoderType: type,
- comptime options: TokenReaderOptions,
-) type {
+pub fn TokenReader(comptime ReaderType: type, comptime options: TokenReaderOptions) type {
return struct {
scanner: Scanner,
reader: ReaderType,
- decoder: DecoderType,
+ decoder: options.DecoderType,
/// The current location in the file (if enabled).
location: if (options.track_location) Location else NoOpLocation = .{},
/// Buffered content read by the reader for the current token.
@@ -232,11 +229,11 @@ pub fn TokenReader(
InvalidPiTarget,
Overflow,
UnexpectedEndOfInput,
- } || ReaderType.Error || DecoderType.Error || Scanner.Error;
+ } || ReaderType.Error || options.DecoderType.Error || Scanner.Error;
- const max_encoded_codepoint_len = @max(DecoderType.max_encoded_codepoint_len, 4);
+ const max_encoded_codepoint_len = @max(options.DecoderType.max_encoded_codepoint_len, 4);
- pub fn init(reader: ReaderType, decoder: DecoderType) Self {
+ pub fn init(reader: ReaderType, decoder: options.DecoderType) Self {
return .{
.scanner = Scanner{},
.reader = reader,
@@ -510,7 +507,7 @@ test "PI target" {
fn testValid(comptime options: TokenReaderOptions, input: []const u8, expected_tokens: []const Token) !void {
var input_stream = std.io.fixedBufferStream(input);
- var input_reader = tokenReader(input_stream.reader(), encoding.Utf8Decoder{}, options);
+ var input_reader = tokenReader(input_stream.reader(), options);
var i: usize = 0;
while (try input_reader.next()) |token| : (i += 1) {
if (i >= expected_tokens.len) {
@@ -530,7 +527,7 @@ fn testValid(comptime options: TokenReaderOptions, input: []const u8, expected_t
fn testInvalid(comptime options: TokenReaderOptions, input: []const u8, expected_error: anyerror) !void {
var input_stream = std.io.fixedBufferStream(input);
- var input_reader = tokenReader(input_stream.reader(), encoding.Utf8Decoder{}, options);
+ var input_reader = tokenReader(input_stream.reader(), options);
while (input_reader.next()) |_| {} else |err| {
try testing.expectEqual(expected_error, err);
}