mirror of
https://git.robbyzambito.me/zaprus/
synced 2026-02-04 03:34:48 +00:00
it works well!
This commit is contained in:
236
src/Client.zig
236
src/Client.zig
@@ -30,166 +30,60 @@ pub fn deinit(self: *Self) void {
|
|||||||
|
|
||||||
/// Used for relay messages and connection handshake.
|
/// Used for relay messages and connection handshake.
|
||||||
/// Assumes Client .init has been called.
|
/// Assumes Client .init has been called.
|
||||||
fn broadcastInitialInterestMessage(self: *Self, msg_bytes: []align(@alignOf(SaprusMessage)) u8) !void {
|
fn broadcastInitialInterestMessage(self: *Self, msg_bytes: []u8) !void {
|
||||||
const writer = self.writer;
|
const writer = self.writer;
|
||||||
|
|
||||||
// const EthernetHeaders = packed struct {
|
const total_len = ((@bitSizeOf(EthernetHeaders) + @bitSizeOf(IpHeaders) + @bitSizeOf(UdpHeaders)) / 8) + msg_bytes.len;
|
||||||
// dest_mac: @Vector(6, u8),
|
|
||||||
|
|
||||||
// src_mac: @Vector(6, u8),
|
|
||||||
|
|
||||||
// ether_type: u16,
|
|
||||||
// };
|
|
||||||
|
|
||||||
const IpHeaders = packed struct {
|
|
||||||
_: u8 = 0x45,
|
|
||||||
// ip_version: u4,
|
|
||||||
// header_length: u4 = 0,
|
|
||||||
type_of_service: u8 = 0,
|
|
||||||
total_length: u16 = 0x04,
|
|
||||||
|
|
||||||
identification: u16 = 0,
|
|
||||||
__: u16 = 0x0,
|
|
||||||
// ethernet_flags: u3 = 0,
|
|
||||||
// fragment_offset: u13 = 0,
|
|
||||||
ttl: u8 = 0,
|
|
||||||
protocol: u8 = 0,
|
|
||||||
|
|
||||||
header_checksum: @Vector(2, u8) = .{ 0, 0 },
|
|
||||||
src_ip: @Vector(4, u8),
|
|
||||||
|
|
||||||
dest_ip: @Vector(4, u8),
|
|
||||||
};
|
|
||||||
|
|
||||||
const UdpHeaders = packed struct {
|
|
||||||
src_port: @Vector(2, u8),
|
|
||||||
|
|
||||||
dest_port: @Vector(2, u8),
|
|
||||||
length: u16,
|
|
||||||
checksum: @Vector(2, u8) = .{ 0, 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
// const total_len = ((@bitSizeOf(IpHeaders) + @bitSizeOf(UdpHeaders)) / 8) + msg_bytes.len;
|
|
||||||
const total_len = 130;
|
|
||||||
std.debug.assert(writer.buffer.len >= total_len);
|
std.debug.assert(writer.buffer.len >= total_len);
|
||||||
_ = writer.consumeAll();
|
_ = writer.consumeAll();
|
||||||
|
|
||||||
// var ether_headers: EthernetHeaders = .{
|
const ether_headers: EthernetHeaders = .{
|
||||||
// .dest_mac = .{ 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff },
|
.dest_mac = .{ 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff },
|
||||||
// // .src_mac = .{ 0xee, 0xee, 0xee, 0xee, 0xee, 0xee },
|
.src_mac = .{ 0xee, 0xee, 0xee, 0xee, 0xee, 0xee },
|
||||||
// .src_mac = blk: {
|
// .src_mac = blk: {
|
||||||
// var output_bytes: [6]u8 = undefined;
|
// var output_bytes: [6]u8 = undefined;
|
||||||
// // const r_bytes = try writer.writableArray(6);
|
// // const r_bytes = try writer.writableArray(6);
|
||||||
// self.rand.bytes(&output_bytes);
|
// self.rand.bytes(&output_bytes);
|
||||||
// break :blk output_bytes;
|
// break :blk output_bytes;
|
||||||
// },
|
// },
|
||||||
// .ether_type = 0x0800,
|
.ether_type = 0x0800,
|
||||||
// };
|
};
|
||||||
|
|
||||||
var ip_headers: IpHeaders = .{
|
// @compileLog((@bitSizeOf(EthernetHeaders) / 8));
|
||||||
|
const ip_headers: IpHeaders = .{
|
||||||
// .ip_version = 0x4,
|
// .ip_version = 0x4,
|
||||||
// .header_length = 0x5,
|
// .header_length = 0x5,
|
||||||
// .total_length = 130, //@intCast(total_len - 8), // 8 is the ethernet frame length (macs + type)
|
.total_length = @intCast(total_len - 92),
|
||||||
.total_length = 0x00,
|
|
||||||
.ttl = 0x64,
|
.ttl = 0x64,
|
||||||
.protocol = 0x11,
|
.protocol = 0x11,
|
||||||
.src_ip = .{ 0xff, 0x02, 0x03, 0x04 },
|
.src_ip = .{ 0xff, 0x02, 0x03, 0x04 },
|
||||||
.dest_ip = .{ 0xff, 0xff, 0xff, 0xff },
|
.dest_ip = .{ 0xff, 0xff, 0xff, 0xff },
|
||||||
};
|
};
|
||||||
|
|
||||||
var udp_headers: UdpHeaders = .{
|
const udp_headers: UdpHeaders = .{
|
||||||
.src_port = .{ 0, 0x01 },
|
.src_port = 0xbbbb,
|
||||||
.dest_port = .{ 0xb8, 0x22 },
|
.dest_port = 8888,
|
||||||
.length = @intCast(msg_bytes.len),
|
.length = @intCast(msg_bytes.len),
|
||||||
};
|
};
|
||||||
_ = &ip_headers;
|
|
||||||
_ = &udp_headers;
|
|
||||||
// _ = ðer_headers;
|
|
||||||
|
|
||||||
// _ = try writer.write(&@as([@bitSizeOf(UdpHeaders) / 8]u8, @bitCast(headers)));
|
try ether_headers.write(writer);
|
||||||
|
try ip_headers.write(writer);
|
||||||
|
try udp_headers.write(writer);
|
||||||
|
|
||||||
// std.mem.byteSwapAllFields(EthernetHeaders, ðer_headers);
|
// Saprus
|
||||||
// try writer.writeStruct(ether_headers, native_endian);
|
const msg_target_bytes = try writer.writableSlice(msg_bytes.len);
|
||||||
|
@memcpy(msg_target_bytes, msg_bytes);
|
||||||
|
var msg_target: *align(1) SaprusMessage = try .bytesAsValue(msg_target_bytes);
|
||||||
|
try msg_target.networkFromNativeEndian();
|
||||||
|
|
||||||
std.mem.byteSwapAllFields(IpHeaders, &ip_headers);
|
|
||||||
try writer.writeStruct(ip_headers, native_endian);
|
|
||||||
|
|
||||||
// std.mem.byteSwapAllFields(UdpHeaders, &udp_headers);
|
|
||||||
// try writer.writeStruct(udp_headers, native_endian);
|
|
||||||
|
|
||||||
// // Ensure buffer is large enough
|
|
||||||
// std.debug.assert(writer.buffer.len > 38 + msg_bytes.len);
|
|
||||||
|
|
||||||
// // Ensure writer is clean
|
|
||||||
// writer.consumeAll();
|
|
||||||
|
|
||||||
// // Destination MAC addr to FF:FF:FF:FF:FF:FF
|
|
||||||
// try writer.write();
|
|
||||||
|
|
||||||
// // Source MAC to random bytes
|
|
||||||
// {
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 96 bits
|
|
||||||
|
|
||||||
// // Set EtherType to IPv4
|
|
||||||
// try writer.write(.{ 0x08, 0x00 });
|
|
||||||
|
|
||||||
// // 112 bits
|
|
||||||
|
|
||||||
// // Set IPv4 version to 4
|
|
||||||
// try writer.writeByte(0x45);
|
|
||||||
|
|
||||||
// // 120 bits
|
|
||||||
|
|
||||||
// // Unset section (Version, IHL, ToS)
|
|
||||||
// writer.advance(2);
|
|
||||||
|
|
||||||
// // 136 bits
|
|
||||||
|
|
||||||
// // Total length
|
|
||||||
// try write.writeInt(u16, 38 + msg_bytes.len);
|
|
||||||
|
|
||||||
// // Destination broadcast
|
|
||||||
// writer.splatByte(0xff, 0x22 - 0x1e);
|
|
||||||
|
|
||||||
// var packet_bytes: [_]u8 = comptime blk: {
|
|
||||||
// var b: [max_message_size]u8 = @splat(0);
|
|
||||||
|
|
||||||
// for (0x1e..0x22) |i| {
|
|
||||||
// b[i] = 0xff;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Set TTL
|
|
||||||
// b[0x16] = 0x40;
|
|
||||||
|
|
||||||
// // Set IPv4 protocol to UDP
|
|
||||||
// b[0x17] = 0x11;
|
|
||||||
|
|
||||||
// // Set interest filter value to 8888.
|
|
||||||
// b[0x24] = 0x22;
|
|
||||||
// b[0x25] = 0xb8;
|
|
||||||
// break :blk &b;
|
|
||||||
// };
|
|
||||||
var msg: *SaprusMessage = try .bytesAsValue(msg_bytes);
|
|
||||||
try msg.networkFromNativeEndian();
|
|
||||||
defer msg.nativeFromNetworkEndian() catch unreachable;
|
|
||||||
|
|
||||||
// std.debug.print("headers: {x}\n", .{@as([@bitSizeOf(UdpHeaders) / 8]u8, @bitCast(headers))});
|
|
||||||
std.debug.print("bytes: {x}\n", .{writer.buffer[0..writer.end]});
|
std.debug.print("bytes: {x}\n", .{writer.buffer[0..writer.end]});
|
||||||
_ = try writer.write(msg_bytes);
|
|
||||||
|
|
||||||
// The byte position within the packet that the saprus message starts at.
|
|
||||||
// const saprus_start_byte = 42;
|
|
||||||
// @memcpy(packet_bytes[saprus_start_byte .. saprus_start_byte + msg_bytes.len], msg_bytes);
|
|
||||||
// _ = try writer.write(packet_bytes[0 .. saprus_start_byte + msg_bytes.len]);
|
|
||||||
try writer.flush();
|
try writer.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn broadcastSaprusMessage(msg_bytes: []align(@alignOf(SaprusMessage)) u8) !void {}
|
// fn broadcastSaprusMessage(msg_bytes: []align(@alignOf(SaprusMessage)) u8) !void {}
|
||||||
|
|
||||||
fn broadcastSaprusMessage(msg_bytes: []align(@alignOf(SaprusMessage)) u8, udp_port: u16) !void {
|
fn broadcastSaprusMessage(msg_bytes: []u8, udp_port: u16) !void {
|
||||||
const msg: *SaprusMessage = try .bytesAsValue(msg_bytes);
|
const msg: *align(1) SaprusMessage = try .bytesAsValue(msg_bytes);
|
||||||
try msg.networkFromNativeEndian();
|
try msg.networkFromNativeEndian();
|
||||||
defer msg.nativeFromNetworkEndian() catch unreachable;
|
defer msg.nativeFromNetworkEndian() catch unreachable;
|
||||||
|
|
||||||
@@ -222,7 +116,7 @@ pub fn sendRelay(self: *Self, payload: []const u8, dest: [4]u8) !void {
|
|||||||
.relay,
|
.relay,
|
||||||
base64Enc.calcSize(payload.len),
|
base64Enc.calcSize(payload.len),
|
||||||
)];
|
)];
|
||||||
const msg: *SaprusMessage = .init(.relay, msg_bytes);
|
const msg: *align(1) SaprusMessage = .init(.relay, msg_bytes);
|
||||||
|
|
||||||
const relay = (try msg.getSaprusTypePayload()).relay;
|
const relay = (try msg.getSaprusTypePayload()).relay;
|
||||||
relay.dest = dest;
|
relay.dest = dest;
|
||||||
@@ -238,15 +132,15 @@ fn randomPort(self: Self) u16 {
|
|||||||
pub fn sendInitialConnection(
|
pub fn sendInitialConnection(
|
||||||
self: Self,
|
self: Self,
|
||||||
payload: []const u8,
|
payload: []const u8,
|
||||||
output_bytes: []align(@alignOf(SaprusMessage)) u8,
|
output_bytes: []u8,
|
||||||
initial_port: u16,
|
initial_port: u16,
|
||||||
) !*SaprusMessage {
|
) !*align(1) SaprusMessage {
|
||||||
const dest_port = self.randomPort();
|
const dest_port = self.randomPort();
|
||||||
const msg_bytes = output_bytes[0..try SaprusMessage.calcSize(
|
const msg_bytes = output_bytes[0..try SaprusMessage.calcSize(
|
||||||
.connection,
|
.connection,
|
||||||
base64Enc.calcSize(payload.len),
|
base64Enc.calcSize(payload.len),
|
||||||
)];
|
)];
|
||||||
const msg: *SaprusMessage = .init(.connection, msg_bytes);
|
const msg: *align(1) SaprusMessage = .init(.connection, msg_bytes);
|
||||||
|
|
||||||
const connection = (try msg.getSaprusTypePayload()).connection;
|
const connection = (try msg.getSaprusTypePayload()).connection;
|
||||||
connection.src_port = initial_port;
|
connection.src_port = initial_port;
|
||||||
@@ -261,7 +155,7 @@ pub fn sendInitialConnection(
|
|||||||
pub fn connect(self: Self, payload: []const u8) !?SaprusConnection {
|
pub fn connect(self: Self, payload: []const u8) !?SaprusConnection {
|
||||||
const initial_port = self.randomPort();
|
const initial_port = self.randomPort();
|
||||||
|
|
||||||
var initial_conn_res: ?*SaprusMessage = null;
|
var initial_conn_res: ?*align(1) SaprusMessage = null;
|
||||||
|
|
||||||
var sock = try network.Socket.create(.ipv4, .udp);
|
var sock = try network.Socket.create(.ipv4, .udp);
|
||||||
defer sock.close();
|
defer sock.close();
|
||||||
@@ -294,6 +188,68 @@ pub fn connect(self: Self, payload: []const u8) !?SaprusConnection {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const EthernetHeaders = struct {
|
||||||
|
dest_mac: @Vector(6, u8),
|
||||||
|
|
||||||
|
src_mac: @Vector(6, u8),
|
||||||
|
|
||||||
|
ether_type: u16,
|
||||||
|
|
||||||
|
fn write(hdr: @This(), writer: *std.Io.Writer) !void {
|
||||||
|
try writer.writeInt(u48, @bitCast(hdr.dest_mac), .big);
|
||||||
|
try writer.writeInt(u48, @bitCast(hdr.src_mac), .big);
|
||||||
|
try writer.writeInt(u16, hdr.ether_type, .big);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const IpHeaders = struct {
|
||||||
|
_: u8 = 0x45,
|
||||||
|
// ip_version: u4,
|
||||||
|
// header_length: u4 = 0,
|
||||||
|
type_of_service: u8 = 0,
|
||||||
|
total_length: u16 = 0x04,
|
||||||
|
|
||||||
|
identification: u16 = 0,
|
||||||
|
__: u16 = 0x0,
|
||||||
|
// ethernet_flags: u3 = 0,
|
||||||
|
// fragment_offset: u13 = 0,
|
||||||
|
ttl: u8 = 0,
|
||||||
|
protocol: u8 = 0,
|
||||||
|
|
||||||
|
header_checksum: @Vector(2, u8) = .{ 0, 0 },
|
||||||
|
src_ip: @Vector(4, u8),
|
||||||
|
|
||||||
|
dest_ip: @Vector(4, u8),
|
||||||
|
|
||||||
|
fn write(hdr: @This(), writer: *std.Io.Writer) !void {
|
||||||
|
try writer.writeInt(u8, 0x45, .big); // ip version and header length
|
||||||
|
try writer.writeByte(hdr.type_of_service);
|
||||||
|
try writer.writeInt(u16, hdr.total_length, .big);
|
||||||
|
try writer.writeInt(u16, hdr.identification, .big);
|
||||||
|
try writer.writeInt(u16, 0x00, .big); // ethernet flags and fragment offset
|
||||||
|
try writer.writeByte(hdr.ttl);
|
||||||
|
try writer.writeByte(hdr.protocol);
|
||||||
|
try writer.writeInt(u16, @bitCast(hdr.header_checksum), .big);
|
||||||
|
try writer.writeInt(u32, @bitCast(hdr.src_ip), .big);
|
||||||
|
try writer.writeInt(u32, @bitCast(hdr.dest_ip), .big);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const UdpHeaders = packed struct {
|
||||||
|
src_port: u16,
|
||||||
|
|
||||||
|
dest_port: u16,
|
||||||
|
length: u16,
|
||||||
|
checksum: @Vector(2, u8) = .{ 0, 0 },
|
||||||
|
|
||||||
|
fn write(hdr: @This(), writer: *std.Io.Writer) !void {
|
||||||
|
try writer.writeInt(u16, hdr.src_port, .big);
|
||||||
|
try writer.writeInt(u16, hdr.dest_port, .big);
|
||||||
|
try writer.writeInt(u16, hdr.length, .big);
|
||||||
|
try writer.writeInt(u16, @bitCast(hdr.checksum), .big);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const SaprusMessage = @import("message.zig").Message;
|
const SaprusMessage = @import("message.zig").Message;
|
||||||
const SaprusConnection = @import("Connection.zig");
|
const SaprusConnection = @import("Connection.zig");
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ pub const Message = packed struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
const SelfBytes = []align(@alignOf(Self)) u8;
|
const SelfBytes = []align(1) u8;
|
||||||
|
|
||||||
type: PacketType,
|
type: PacketType,
|
||||||
length: u16,
|
length: u16,
|
||||||
@@ -81,9 +81,9 @@ pub const Message = packed struct {
|
|||||||
/// This properly initializes the top level headers within the slice.
|
/// This properly initializes the top level headers within the slice.
|
||||||
/// This is used for creating new messages. For reading messages from the network,
|
/// This is used for creating new messages. For reading messages from the network,
|
||||||
/// see: networkBytesAsValue.
|
/// see: networkBytesAsValue.
|
||||||
pub fn init(@"type": PacketType, bytes: []align(@alignOf(Self)) u8) *Self {
|
pub fn init(@"type": PacketType, bytes: []u8) *align(1) Self {
|
||||||
std.debug.assert(bytes.len >= @sizeOf(Self));
|
std.debug.assert(bytes.len >= @sizeOf(Self));
|
||||||
const res: *Self = @ptrCast(bytes.ptr);
|
const res: *align(1) Self = @ptrCast(bytes.ptr);
|
||||||
res.type = @"type";
|
res.type = @"type";
|
||||||
res.length = @intCast(bytes.len - @sizeOf(Self));
|
res.length = @intCast(bytes.len - @sizeOf(Self));
|
||||||
return res;
|
return res;
|
||||||
@@ -100,15 +100,15 @@ pub const Message = packed struct {
|
|||||||
return @intCast(payload_len + @sizeOf(Self) + header_size);
|
return @intCast(payload_len + @sizeOf(Self) + header_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getRelay(self: *Self) *align(1) Relay {
|
fn getRelay(self: *align(1) Self) *align(1) Relay {
|
||||||
return std.mem.bytesAsValue(Relay, &self.bytes);
|
return std.mem.bytesAsValue(Relay, &self.bytes);
|
||||||
}
|
}
|
||||||
fn getConnection(self: *Self) *align(1) Connection {
|
fn getConnection(self: *align(1) Self) *align(1) Connection {
|
||||||
return std.mem.bytesAsValue(Connection, &self.bytes);
|
return std.mem.bytesAsValue(Connection, &self.bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the message Saprus payload.
|
/// Access the message Saprus payload.
|
||||||
pub fn getSaprusTypePayload(self: *Self) MessageTypeError!(union(PacketType) {
|
pub fn getSaprusTypePayload(self: *align(1) Self) MessageTypeError!(union(PacketType) {
|
||||||
relay: *align(1) Relay,
|
relay: *align(1) Relay,
|
||||||
file_transfer: void,
|
file_transfer: void,
|
||||||
connection: *align(1) Connection,
|
connection: *align(1) Connection,
|
||||||
@@ -122,7 +122,7 @@ pub const Message = packed struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the message to native endianness from network endianness in-place.
|
/// Convert the message to native endianness from network endianness in-place.
|
||||||
pub fn nativeFromNetworkEndian(self: *Self) MessageTypeError!void {
|
pub fn nativeFromNetworkEndian(self: *align(1) Self) MessageTypeError!void {
|
||||||
self.type = @enumFromInt(bigToNative(
|
self.type = @enumFromInt(bigToNative(
|
||||||
@typeInfo(@TypeOf(self.type)).@"enum".tag_type,
|
@typeInfo(@TypeOf(self.type)).@"enum".tag_type,
|
||||||
@intFromEnum(self.type),
|
@intFromEnum(self.type),
|
||||||
@@ -146,7 +146,7 @@ pub const Message = packed struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the message to network endianness from native endianness in-place.
|
/// Convert the message to network endianness from native endianness in-place.
|
||||||
pub fn networkFromNativeEndian(self: *Self) MessageTypeError!void {
|
pub fn networkFromNativeEndian(self: *align(1) Self) MessageTypeError!void {
|
||||||
try switch (try self.getSaprusTypePayload()) {
|
try switch (try self.getSaprusTypePayload()) {
|
||||||
.relay => {},
|
.relay => {},
|
||||||
.connection => |*con| con.*.networkFromNativeEndian(),
|
.connection => |*con| con.*.networkFromNativeEndian(),
|
||||||
@@ -161,7 +161,7 @@ pub const Message = packed struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert network endian bytes to a native endian value in-place.
|
/// Convert network endian bytes to a native endian value in-place.
|
||||||
pub fn networkBytesAsValue(bytes: SelfBytes) MessageParseError!*Self {
|
pub fn networkBytesAsValue(bytes: SelfBytes) MessageParseError!*align(1) Self {
|
||||||
const res = std.mem.bytesAsValue(Self, bytes);
|
const res = std.mem.bytesAsValue(Self, bytes);
|
||||||
try res.nativeFromNetworkEndian();
|
try res.nativeFromNetworkEndian();
|
||||||
return .bytesAsValue(bytes);
|
return .bytesAsValue(bytes);
|
||||||
@@ -169,7 +169,7 @@ pub const Message = packed struct {
|
|||||||
|
|
||||||
/// Create a structured view of the bytes without initializing the length or type,
|
/// Create a structured view of the bytes without initializing the length or type,
|
||||||
/// and without converting the endianness.
|
/// and without converting the endianness.
|
||||||
pub fn bytesAsValue(bytes: SelfBytes) MessageParseError!*Self {
|
pub fn bytesAsValue(bytes: SelfBytes) MessageParseError!*align(1) Self {
|
||||||
const res = std.mem.bytesAsValue(Self, bytes);
|
const res = std.mem.bytesAsValue(Self, bytes);
|
||||||
return switch (res.type) {
|
return switch (res.type) {
|
||||||
.relay, .connection => if (bytes.len == res.length + @sizeOf(Self))
|
.relay, .connection => if (bytes.len == res.length + @sizeOf(Self))
|
||||||
@@ -183,9 +183,9 @@ pub const Message = packed struct {
|
|||||||
|
|
||||||
/// Deprecated.
|
/// Deprecated.
|
||||||
/// If I need the bytes, I should just pass around the slice that is backing this to begin with.
|
/// If I need the bytes, I should just pass around the slice that is backing this to begin with.
|
||||||
pub fn asBytes(self: *Self) SelfBytes {
|
pub fn asBytes(self: *align(1) Self) SelfBytes {
|
||||||
const size = @sizeOf(Self) + self.length;
|
const size = @sizeOf(Self) + self.length;
|
||||||
return @as([*]align(@alignOf(Self)) u8, @ptrCast(self))[0..size];
|
return @as([*]align(1) u8, @ptrCast(self))[0..size];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user