I want to create a base64 code as an initial step to create a TLV (Tag-Length-Value) format, I have the below golang code that is working fine:
package main
import (
"bytes"
"encoding/base64"
"fmt"
)
func getTLVForValue(tagNum, tagValue string) []byte {
tagBuf := []byte(tagNum)
tagValueLenBuf := []byte{byte(len(tagValue))}
tagValueBuf := []byte(tagValue)
bufsArray := [][]byte{tagBuf, tagValueLenBuf, tagValueBuf}
return bytes.Join(bufsArray, nil)
}
func main() {
//1. Seller Name
sellerNameBuf := getTLVForValue("1", "Salah Hospital")
//2. VAT Registration
vatRegistrationNameBuf := getTLVForValue("2", "312345678901233")
tagBufsArray := [][]byte{
sellerNameBuf,
vatRegistrationNameBuf,
}
qrCodeBuf := bytes.Join(tagBufsArray, nil)
qrCodeB64 := base64.StdEncoding.EncodeToString(qrCodeBuf)
fmt.Println(qrCodeB64)
}
And trying to replicate it in zig as:
const std = @import("std");
fn getTLVForValue(allocator: *std.mem.Allocator, tagNum: []const u8, tagValue: []const u8) ![]u8 {
var tagBuf = try allocator.alloc(u8, tagNum.len);
std.mem.copy(u8, tagBuf, tagNum);
var tagValueLenBuf = try allocator.alloc(u8, 1);
tagValueLenBuf[0] = @intCast(tagValue.len);
var bufsArray = [_][]u8{tagBuf, tagValueLenBuf, tagValue};
return std.mem.concat(allocator, u8, bufsArray);
}
pub fn main() !void {
var allocator = std.heap.page_allocator;
//1. Seller Name
const sellerNameBuf = try getTLVForValue(&allocator, "1", "Salah Hospital");
//2. VAT Registration
const vatRegistrationNameBuf = try getTLVForValue(&allocator, "2", "312345678901233");
const tagBufsArray = [_][]u8{
sellerNameBuf,
vatRegistrationNameBuf,
};
const qrCodeBuf = std.mem.concat(&allocator, u8, tagBufsArray) catch |err| {
std.debug.print("Error: {}\n", .{err});
return;
};
const qrCodeB64 = std.base64.standard.encode(qrCodeBuf);
std.debug.print("{}\n", .{qrCodeB64});
}
But it is not working fine, as I got the error:
qr.zig:8:53: error: expected type '[]u8', found '[]const u8'
var bufsArray = [_][]u8{tagBuf, tagValueLenBuf, tagValue};
^~~~~~~~
qr.zig:8:53: note: cast discards const qualifier
how can I fix it, and if there is anything wrong in my approach i do appreciate your guidines.
I solved it with the following code:
const std = @import("std");
fn getTLVForValue(allocator: std.mem.Allocator, tagNum: []const u8, tagValue: []const u8) ![]u8 {
var tagBuf = try allocator.alloc(u8, tagNum.len);
std.mem.copy(u8, tagBuf, tagNum);
var tagValueLenBuf = try allocator.alloc(u8, 1);
tagValueLenBuf[0] = @intCast(tagValue.len);
var bufsArray = [_][]const u8{tagBuf, tagValueLenBuf, tagValue};
return std.mem.concat(allocator, u8, &bufsArray);
}
pub fn main() !void {
var allocator = std.heap.page_allocator;
//1. Seller Name
const sellerNameBuf = try getTLVForValue(allocator, "01", "Bobs Basement Records");
//2. VAT Registration
const vatRegistrationNameBuf = try getTLVForValue(allocator, "02", "312345678901233");
//3. Time stamp
const timeStampBuf = try getTLVForValue(allocator, "03", "12/12/2023");
//4. tax Total
const taxTotalNameBuf = try getTLVForValue(allocator, "04", "1000");
//5. Vat Total
const vatTotalBuf = try getTLVForValue(allocator, "05", "115");
//6. Hashed XML
const hashedXmlBuf = try getTLVForValue(allocator, "06", "dsds");
//7. key
const keyBuf = try getTLVForValue(allocator, "07", "125");
//8. Signature
const signatureBuf = try getTLVForValue(allocator, "08", "dsfsd");
const tagBufsArray = [_][]u8{
sellerNameBuf,
vatRegistrationNameBuf,
timeStampBuf,
taxTotalNameBuf,
vatTotalBuf,
hashedXmlBuf,
keyBuf,
signatureBuf,
};
const qrCodeBuf = std.mem.concat(allocator, u8, &tagBufsArray) catch |err| {
std.debug.print("Error: {}\n", .{err});
return;
};
std.debug.print("{any}\n", .{qrCodeBuf});
std.debug.print("{}\n", .{ @TypeOf(qrCodeBuf) });
const slice: []const u8 = qrCodeBuf;
const hexString = try std.fmt.allocPrint(std.heap.page_allocator, "{}", .{std.fmt.fmtSliceHexUpper(slice)});
defer std.heap.page_allocator.free(hexString);
std.debug.print("Hex string: {s}\n", .{hexString});
}