Skip to content

Commit 419cbba

Browse files
committed
Adds new tests and fixes a few issues
1 parent fcfab29 commit 419cbba

File tree

4 files changed

+124
-9
lines changed

4 files changed

+124
-9
lines changed

src/decoder.zig

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,18 @@ pub fn decodeAlloc(comptime T: type, allocator: std.mem.Allocator, data: []const
2929
.optional => |info| decodeOption(info.child, allocator, data, decodeAlloc),
3030
.pointer => |info| {
3131
if (info.size == .slice) {
32-
return decodeSlice(info.child, allocator, data, decodeAlloc);
32+
if (info.child == u8) {
33+
// Handle string slices - decode as []u8 and convert if needed
34+
const result = try decodeSlice(u8, allocator, data, decodeAlloc);
35+
if (T == []const u8) {
36+
// Convert []u8 to []const u8
37+
return .{ .value = result.value, .bytes_read = result.bytes_read };
38+
} else {
39+
return result;
40+
}
41+
} else {
42+
return decodeSlice(info.child, allocator, data, decodeAlloc);
43+
}
3344
} else {
3445
return error.UnsupportedType;
3546
}
@@ -97,7 +108,7 @@ pub fn decodeCompact(comptime T: type, data: []const u8) !DecodeResult(T) {
97108
}
98109
}
99110

100-
pub fn decodeSlice(comptime T: type, allocator: std.mem.Allocator, data: []const u8, decoder: anytype) !DecodeResult(if (T == u8) []const u8 else []T) {
111+
pub fn decodeSlice(comptime T: type, allocator: std.mem.Allocator, data: []const u8, decoder: anytype) !DecodeResult(if (T == u8) []u8 else []T) {
101112
const length = try decodeCompact(u32, data);
102113
var offset = length.bytes_read;
103114

src/encoder.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ pub fn encode(value: anytype, buffer: []u8) !usize {
187187
const array_info = @typeInfo(info.child).array;
188188
// Convert pointer to array into a slice
189189
const slice = value[0..array_info.len];
190-
return encodeFixedArray(info.child, info.len, slice, buffer, encode);
190+
return encodeArray(array_info.child, slice, buffer, encode);
191191
}
192192

193193
std.debug.print("Unsupported type: {s}\n", .{@typeName(T)});

src/tests.zig

Lines changed: 100 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,46 @@ const std = @import("std");
22
const encoder = @import("encoder.zig");
33
const decoder = @import("decoder.zig");
44

5-
test "encode-and-decode-array" {
5+
test "encode-and-decode-vector-of-strings" {
6+
const allocator = std.testing.allocator;
7+
8+
var strings = [_][]const u8{ "Hello", "World" };
9+
10+
const test_cases = [_]struct {
11+
value: [][]const u8,
12+
encoded: []const u8,
13+
}{
14+
.{
15+
.value = strings[0..],
16+
.encoded = &[_]u8{
17+
0x08, // Compact length (2)
18+
0x14, // Compact length (5) for "Hello"
19+
0x48, 0x65, 0x6c, 0x6c, 0x6f, // "Hello"
20+
0x14, // Compact length (5) for "World"
21+
0x57, 0x6f, 0x72, 0x6c, 0x64, // "World"
22+
},
23+
},
24+
};
25+
26+
for (test_cases) |tc| {
27+
// Test encoding
28+
const buffer = try encoder.encodeAlloc(allocator, tc.value);
29+
defer allocator.free(buffer);
30+
try std.testing.expectEqualSlices(u8, tc.encoded, buffer);
31+
32+
// Test decoding
33+
const result = try decoder.decodeAlloc([][]const u8, allocator, tc.encoded);
34+
defer allocator.free(result.value);
35+
defer for (result.value) |str| allocator.free(str);
36+
try std.testing.expectEqual(result.bytes_read, tc.encoded.len);
37+
try std.testing.expectEqual(result.value.len, tc.value.len);
38+
for (result.value, tc.value) |decoded_str, expected_str| {
39+
try std.testing.expectEqualStrings(expected_str, decoded_str);
40+
}
41+
}
42+
}
43+
44+
test "encode-and-decode-vector-of-u32" {
645
const allocator = std.testing.allocator;
746

847
const test_cases = [_]struct {
@@ -137,20 +176,61 @@ test "encode-and-decode-option" {
137176
}
138177

139178
test "encode-and-decode-string" {
179+
// Test both []const u8 and []u8 string types for SCALE encoding/decoding
140180
const allocator = std.testing.allocator;
141181

142-
const test_cases = [_]struct {
182+
// Test cases for []const u8 (immutable strings)
183+
const const_test_cases = [_]struct {
143184
decoded: []const u8,
144185
encoded: []const u8,
145186
}{
146187
.{
147188
.decoded = "Hello World",
148189
.encoded = &[_]u8{ 0x2c, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64 },
149190
},
150-
// TODO: Add more test cases
191+
.{
192+
.decoded = "",
193+
.encoded = &[_]u8{0x00},
194+
},
195+
.{
196+
.decoded = "A",
197+
.encoded = &[_]u8{ 0x04, 0x41 },
198+
},
199+
.{
200+
.decoded = "Hello",
201+
.encoded = &[_]u8{ 0x14, 0x48, 0x65, 0x6c, 0x6c, 0x6f },
202+
},
203+
.{
204+
.decoded = "This is a longer string for testing",
205+
.encoded = &[_]u8{ 0x8c, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67 },
206+
},
151207
};
152208

153-
for (test_cases) |tc| {
209+
// Test cases for []u8 (mutable strings)
210+
const mutable_test_cases = [_]struct {
211+
decoded: []u8,
212+
encoded: []const u8,
213+
}{
214+
.{
215+
.decoded = try allocator.dupe(u8, "Hello World"),
216+
.encoded = &[_]u8{ 0x2c, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64 },
217+
},
218+
.{
219+
.decoded = try allocator.dupe(u8, ""),
220+
.encoded = &[_]u8{0x00},
221+
},
222+
.{
223+
.decoded = try allocator.dupe(u8, "Test"),
224+
.encoded = &[_]u8{ 0x10, 0x54, 0x65, 0x73, 0x74 },
225+
},
226+
.{
227+
.decoded = try allocator.dupe(u8, "Mutable String"),
228+
.encoded = &[_]u8{ 0x38, 0x4d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67 },
229+
},
230+
};
231+
232+
// Test []const u8 encoding and decoding
233+
for (const_test_cases) |tc| {
154234
// Test encoding
155235
const buffer = try encoder.encodeAlloc(allocator, tc.decoded);
156236
defer allocator.free(buffer);
@@ -162,6 +242,22 @@ test "encode-and-decode-string" {
162242
try std.testing.expectEqual(result.bytes_read, tc.encoded.len);
163243
try std.testing.expectEqualStrings(tc.decoded, result.value);
164244
}
245+
246+
// Test []u8 encoding and decoding
247+
for (mutable_test_cases) |tc| {
248+
defer allocator.free(tc.decoded);
249+
250+
// Test encoding
251+
const buffer = try encoder.encodeAlloc(allocator, tc.decoded);
252+
defer allocator.free(buffer);
253+
try std.testing.expectEqualSlices(u8, tc.encoded, buffer);
254+
255+
// Test decoding
256+
const result = try decoder.decodeAlloc([]u8, allocator, tc.encoded);
257+
defer allocator.free(result.value);
258+
try std.testing.expectEqual(result.bytes_read, tc.encoded.len);
259+
try std.testing.expectEqualStrings(tc.decoded, result.value);
260+
}
165261
}
166262

167263
test "encode-and-decode-bool" {

src/util.zig

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,23 @@ pub fn calculateEncodedSize(value: anytype) !usize {
2222
if (info.child == u8) {
2323
return calculateCompactSize(@intCast(value.len)) + value.len;
2424
} else {
25-
return calculateCompactSize(@intCast(value.len)) + (value.len * @sizeOf(info.child));
25+
var size = calculateCompactSize(@intCast(value.len));
26+
for (value) |item| {
27+
size += try calculateEncodedSize(item);
28+
}
29+
return size;
2630
}
2731
} else if (info.size == .one and @typeInfo(info.child) == .array) {
2832
// Handle pointers to arrays (like string literals)
2933
const array_info = @typeInfo(info.child).array;
3034
if (array_info.child == u8) {
3135
return calculateCompactSize(@intCast(array_info.len)) + array_info.len;
3236
} else {
33-
return calculateCompactSize(@intCast(array_info.len)) + (array_info.len * @sizeOf(array_info.child));
37+
var size = calculateCompactSize(@intCast(array_info.len));
38+
for (value) |item| {
39+
size += try calculateEncodedSize(item);
40+
}
41+
return size;
3442
}
3543
}
3644

0 commit comments

Comments
 (0)