I'm having the below code, that is building a Base64 code to be used for TLV QR code, the code got generated with me is correct, but I'm tried to decode
it to cross check the validation in the code itself, but looks I stuck in allocating the correct length
to be considered, the code is below as well as uploaded here: https://zigbin.io/5688ca:
我有下面的代码,那就是构建一个用于TLV二维码的Base64代码,与我生成的代码是正确的,但我试图解码它以交叉检查代码本身的验证,但看起来我卡住了分配正确的长度要考虑,代码在下面以及上传到这里:https://zigbin.io/5688ca:
const std = @import("std");
pub const Tlv = struct {
tag: u8,
value: []const u8,
pub fn init(tag: u8, value: []const u8) Tlv {
return .{ .tag = tag, .value = value };
}
pub fn write(tlv: Tlv, writer: anytype) !void {
try writer.writeByte(tlv.tag);
try writer.writeByte(@intCast(tlv.value.len));
_ = try writer.write(tlv.value);
}
pub fn encode(tlvs: []const Tlv, allocator: std.mem.Allocator) ![]const u8 {
var buf = std.ArrayList(u8).init(allocator);
defer buf.deinit();
const writer = buf.writer();
for (tlvs) |tlv| {
try tlv.write(writer);
}
const E = std.base64.standard.Encoder;
const encoded = try allocator.alloc(u8, E.calcSize(buf.items.len));
_ = E.encode(encoded, buf.items);
return encoded;
}
pub fn decode(encoded: []const u8, allocator: std.mem.Allocator) !void { // !struct { []Tlv, []u8 } {
var E = std.base64.standard.Decoder;
std.debug.print("encoded size: {any} / {any}\n", .{E.calcSizeForSlice(encoded), encoded.len});
const decoded = try allocator.alloc(u8, encoded.len);
defer allocator.free(decoded);
try E.decode(decoded, encoded);
var tlvs = std.ArrayList(Tlv).init(allocator);
var i: usize = 0;
while (i < decoded.len-1) {
const len = decoded[i+1];
std.debug.print("TLV elements: {any} / {s}\n", .{ decoded[i], decoded[i+2..][0..len]});
try tlvs.append(.{.tag = decoded[i], .value = decoded[i+2..][0..len] });
i += 2 + len;
}
}
};
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
const allocator = arena.allocator();
const tlvs = [_]Tlv{
Tlv.init(1, "Bonz carpet"),
Tlv.init(2, "310122393500003"),
Tlv.init(3, "2022-04-25T15:30:00Z"),
Tlv.init(4, "1200.00"),
Tlv.init(5, "180.00"),
};
const encoded = try Tlv.encode(&tlvs, allocator);
defer allocator.free(encoded);
std.debug.print("Base64: {s}\n", .{ encoded});
try Tlv.decode(encoded, allocator);
}
The output I got is:
我得到的输出是:
Base64: AQtCb256IGNhcnBldAIPMzEwMTIyMzkzNTAwMDAzAxQyMDIyLTA0LTI1VDE1OjMwOjAwWgQHMTIwMC4wMAUGMTgwLjAw
encoded size: 69 / 92
TLV elements: 1 / Bonz carpet
TLV elements: 2 / 310122393500003
TLV elements: 3 / 2022-04-25T15:30:00Z
TLV elements: 4 / 1200.00
TLV elements: 5 / 180.00
thread 1 panic: index out of bounds: index 241, len 92
example.zig:40:85: 0x221ad8 in decode (output.s)
std.debug.print("TLV elements: {any} / {s}\n", .{ decoded[i], decoded[i+2..][0..len]});
^
example.zig:61:19: 0x222ff8 in main (output.s)
try Tlv.decode(encoded, allocator);
^
/opt/compiler-explorer/zig-master/lib/std/start.zig:370:37: 0x21f9b5 in posixCallMainAndExit (output.s)
var i: usize = 0;
^
/opt/compiler-explorer/zig-master/lib/std/start.zig:243:5: 0x21f4a1 in _start (output.s)
asm volatile (switch (native_arch) {
^
???:?:?: 0x0 in ??? (???)
Program terminated with signal: SIGSEGV
Exit code: 139
I tried allocating the length using E.calcSizeForSlice(encoded)
, which is equal 92
(i.e. the correct length to be allocated) but I got the error:
我尝试使用E.calcSizeForSlice(编码)分配长度,它等于92(即要分配的正确长度),但得到错误:
error: expected type 'usize', found 'error{InvalidCharacter,InvalidPadding,NoSpaceLeft}!usize'
try writer.writeByte(@intCast(tlv.value.len));
~~~~~~^~~~~~~~~~
note: cannot convert error union to payload type
note: consider using 'try', 'catch', or 'if'
更多回答
优秀答案推荐
I fixed it by replaced const decoded = try allocator.alloc(u8, E.calcSizeForSlice(encoded));
by:
我将其修复为:替换常量解码=try allocator.alloc(U8,E.calcSizeForSlice(Encode));替换为:
const decodedLen = try E.calcSizeForSlice(encoded);
const decoded = try allocator.alloc(u8, decodedLen);
Now my full code is https://zigbin.io/159568:
现在我的完整代码是https://zigbin.io/159568:
const std = @import("std");
pub const Tlv = struct {
tag: u8,
value: []const u8,
pub fn init(tag: u8, value: []const u8) Tlv {
return .{ .tag = tag, .value = value };
}
pub fn write(tlv: Tlv, writer: anytype) !void {
try writer.writeByte(tlv.tag);
try writer.writeByte(@intCast(tlv.value.len));
_ = try writer.write(tlv.value);
}
pub fn encode(tlvs: []const Tlv, allocator: std.mem.Allocator) ![]const u8 {
var buf = std.ArrayList(u8).init(allocator);
defer buf.deinit();
const writer = buf.writer();
for (tlvs) |tlv| {
try tlv.write(writer);
}
const E = std.base64.standard.Encoder;
const encoded = try allocator.alloc(u8, E.calcSize(buf.items.len));
_ = E.encode(encoded, buf.items);
return encoded;
}
pub fn decode(encoded: []const u8, allocator: std.mem.Allocator) !struct { tlvs: std.ArrayList(Tlv), decoded: []u8 } {
var E = std.base64.standard.Decoder;
const decodedLen = try E.calcSizeForSlice(encoded);
const decoded = try allocator.alloc(u8, decodedLen);
defer allocator.free(decoded);
try E.decode(decoded, encoded);
var tlvs = std.ArrayList(Tlv).init(allocator);
var i: usize = 0;
while (i < decoded.len-1) {
const len = decoded[i+1];
// if (i + 2 + len > decoded.len) {
// break;
// }
try tlvs.append(.{.tag = decoded[i], .value = decoded[i+2..][0..len] });
i += 2 + len;
}
return .{ .tlvs = tlvs, .decoded = decoded };
}
};
pub const Tlvs = struct {
items: []const Tlv,
pub fn tlvsToJson(self: Tlvs, allocator: std.mem.Allocator) ![]u8 {
var json = try allocator.alloc(u8, 2);
json[0] = '[';
json[1] = ']';
var i: usize = 0;
while (i < self.items.len) {
const tlv = self.items[i];
if (i == 0) {
json = try std.fmt.allocPrint(allocator, "{s}{{\"tag\": {d}, \"value\": \"{s}\"}}", .{json[0..json.len-1], tlv.tag, tlv.value});
} else {
json = try std.fmt.allocPrint(allocator, "{s},{{\"tag\": {d}, \"value\": \"{s}\"}}", .{json[0..json.len-1], tlv.tag, tlv.value});
}
i += 1;
}
json = try std.fmt.allocPrint(allocator, "{s}]", .{json});
return json;
}
};
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
const allocator = arena.allocator();
const tlvs = [_]Tlv{
Tlv.init(1, "Bonz carpet"),
Tlv.init(2, "310122393500003"),
Tlv.init(3, "2022-04-25T15:30:00Z"),
Tlv.init(4, "1200.00"),
Tlv.init(5, "180.00"),
};
const encoded = try Tlv.encode(&tlvs, allocator);
defer allocator.free(encoded);
std.debug.print("Base64: {s}\n", .{ encoded});
const result = try Tlv.decode(encoded, allocator);
for (result.tlvs.items) |tlv| {
std.debug.print("TLV.tagNum = {any}, TLV.tagName = {s}\n", .{tlv.tag, tlv.value});
}
std.debug.print("Decoded: {s}\n", .{std.mem.bytesAsSlice(u8, result.decoded)});
const tlvs2 = Tlvs{ .items = result.tlvs.items };
const json = try tlvs2.tlvsToJson(allocator);
std.debug.print("{s}\n", .{json});
// Free the memory allocated for the JSON string
allocator.free(json);
// Free the memory allocated for tlvs and decoded
result.tlvs.deinit();
allocator.free(result.decoded);
}
更多回答
我是一名优秀的程序员,十分优秀!