| ... | @@ -2215,33 +2215,54 @@ test writeVarPackedInt { | ... | @@ -2215,33 +2215,54 @@ test writeVarPackedInt { |
| 2215 | try testing.expectEqual(T{ .a = 1, .b = value, .c = 4 }, st); | 2215 | try testing.expectEqual(T{ .a = 1, .b = value, .c = 4 }, st); |
| 2216 | } | 2216 | } |
| 2217 | | 2217 | |
| 2218 | /// Swap the byte order of all the members of the fields of a struct | 2218 | /// Deprecated: use `byteSwap` instead. |
| 2219 | /// (Changing their endianness) | 2219 | pub const byteSwapAllFields = byteSwap; |
| 2220 | pub fn byteSwapAllFields(comptime S: type, ptr: *S) void { | 2220 | |
| 2221 | byteSwapAllFieldsAligned(S, .of(S), ptr); | 2221 | /// Deprecated: use `byteSwapAligned` instead. |
| | 2222 | pub const byteSwapAllFieldsAligned = byteSwapAligned; |
| | 2223 | |
| | 2224 | /// Reverses the byte order. |
| | 2225 | /// Handles structs, unions, arrays, enums, floats, and integers recursively. |
| | 2226 | /// The order of extern struct fields and array elements remains unchanged and |
| | 2227 | /// will be byte swapped recursively. |
| | 2228 | /// Useful for converting between little-endian and big-endian representations. |
| | 2229 | pub fn byteSwap(comptime S: type, ptr: *S) void { |
| | 2230 | byteSwapAligned(S, .of(S), ptr); |
| 2222 | } | 2231 | } |
| 2223 | | 2232 | |
| 2224 | /// Swap the byte order of all the members of the fields of a struct | 2233 | /// Reverses the byte order. |
| 2225 | /// (Changing their endianness) | 2234 | /// Handles structs, unions, arrays, enums, floats, and integers recursively. |
| 2226 | pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *align(a.toByteUnits()) S) void { | 2235 | /// The order of extern struct fields and array elements remains unchanged and |
| | 2236 | /// will be byte swapped recursively. |
| | 2237 | /// Useful for converting between little-endian and big-endian representations. |
| | 2238 | pub fn byteSwapAligned( |
| | 2239 | comptime S: type, |
| | 2240 | comptime a: Alignment, |
| | 2241 | ptr: *align(a.toByteUnits()) S, |
| | 2242 | ) void { |
| 2227 | switch (@typeInfo(S)) { | 2243 | switch (@typeInfo(S)) { |
| 2228 | .@"struct" => |@"struct"| { | 2244 | .@"struct" => |@"struct"| { |
| 2229 | if (@"struct".backing_integer) |Int| { | 2245 | if (@"struct".backing_integer) |Int| { |
| 2230 | ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*)))); | 2246 | ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*)))); |
| 2231 | } else inline for (@"struct".field_types, @"struct".field_names, @"struct".field_attrs) |f_type, f_name, f_attr| { | 2247 | } else { |
| 2232 | switch (@typeInfo(f_type)) { | 2248 | if (@"struct".layout != .@"extern") { |
| 2233 | .@"struct" => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)), | 2249 | @compileError("byteSwapAligned expects a packed or extern struct"); |
| 2234 | .@"union", .array => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)), | 2250 | } |
| 2235 | .@"enum" => { | 2251 | inline for (@"struct".field_types, @"struct".field_names, @"struct".field_attrs) |f_type, f_name, f_attr| { |
| 2236 | @field(ptr, f_name) = @fromBackingInt(@intCast(@byteSwap(@backingInt(@field(ptr, f_name))))); | 2252 | switch (@typeInfo(f_type)) { |
| 2237 | }, | 2253 | .@"struct" => byteSwapAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)), |
| 2238 | .bool => {}, | 2254 | .@"union", .array => byteSwapAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)), |
| 2239 | .float => |float| { | 2255 | .@"enum" => { |
| 2240 | @field(ptr, f_name) = @bitCast(@byteSwap(@as(@Int(.unsigned, float.bits), @bitCast(@field(ptr, f_name))))); | 2256 | @field(ptr, f_name) = @fromBackingInt(@byteSwap(@backingInt(@field(ptr, f_name)))); |
| 2241 | }, | 2257 | }, |
| 2242 | else => { | 2258 | .bool => {}, |
| 2243 | @field(ptr, f_name) = @byteSwap(@field(ptr, f_name)); | 2259 | .float => |float| { |
| 2244 | }, | 2260 | @field(ptr, f_name) = @bitCast(@byteSwap(@as(@Int(.unsigned, float.bits), @bitCast(@field(ptr, f_name))))); |
| | 2261 | }, |
| | 2262 | else => { |
| | 2263 | @field(ptr, f_name) = @byteSwap(@field(ptr, f_name)); |
| | 2264 | }, |
| | 2265 | } |
| 2245 | } | 2266 | } |
| 2246 | } | 2267 | } |
| 2247 | }, | 2268 | }, |
| ... | @@ -2249,7 +2270,7 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a | ... | @@ -2249,7 +2270,7 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a |
| 2249 | ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*)))); | 2270 | ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*)))); |
| 2250 | } else { | 2271 | } else { |
| 2251 | if (@"union".layout != .@"extern") { | 2272 | if (@"union".layout != .@"extern") { |
| 2252 | @compileError("byteSwapAllFields expects a packed or extern union"); | 2273 | @compileError("byteSwapAligned expects a packed or extern union"); |
| 2253 | } | 2274 | } |
| 2254 | | 2275 | |
| 2255 | const first_size = @bitSizeOf(@"union".field_types[0]); | 2276 | const first_size = @bitSizeOf(@"union".field_types[0]); |
| ... | @@ -2266,13 +2287,21 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a | ... | @@ -2266,13 +2287,21 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a |
| 2266 | .array => |array| { | 2287 | .array => |array| { |
| 2267 | byteSwapAllElements(array.child, ptr); | 2288 | byteSwapAllElements(array.child, ptr); |
| 2268 | }, | 2289 | }, |
| | 2290 | .@"enum" => { |
| | 2291 | ptr.* = @fromBackingInt(@byteSwap(@backingInt(ptr.*))); |
| | 2292 | }, |
| | 2293 | .bool => {}, |
| | 2294 | .float => |float| { |
| | 2295 | const int_repr: @Int(.unsigned, float.bits) = @bitCast(ptr.*); |
| | 2296 | ptr.* = @bitCast(@byteSwap(int_repr)); |
| | 2297 | }, |
| 2269 | else => { | 2298 | else => { |
| 2270 | ptr.* = @byteSwap(ptr.*); | 2299 | ptr.* = @byteSwap(ptr.*); |
| 2271 | }, | 2300 | }, |
| 2272 | } | 2301 | } |
| 2273 | } | 2302 | } |
| 2274 | | 2303 | |
| 2275 | test byteSwapAllFields { | 2304 | test byteSwap { |
| 2276 | const T = extern struct { | 2305 | const T = extern struct { |
| 2277 | f0: u8, | 2306 | f0: u8, |
| 2278 | f1: u16, | 2307 | f1: u16, |
| ... | @@ -2304,6 +2333,9 @@ test byteSwapAllFields { | ... | @@ -2304,6 +2333,9 @@ test byteSwapAllFields { |
| 2304 | } align(4), | 2333 | } align(4), |
| 2305 | f2: u32, | 2334 | f2: u32, |
| 2306 | }; | 2335 | }; |
| | 2336 | const E = enum(u32) { |
| | 2337 | _, |
| | 2338 | }; |
| 2307 | var s = T{ | 2339 | var s = T{ |
| 2308 | .f0 = 0x12, | 2340 | .f0 = 0x12, |
| 2309 | .f1 = 0x1234, | 2341 | .f1 = 0x1234, |
| ... | @@ -2327,10 +2359,14 @@ test byteSwapAllFields { | ... | @@ -2327,10 +2359,14 @@ test byteSwapAllFields { |
| 2327 | .f1 = .{ .f0 = 0x123456789ABCDEF0 }, | 2359 | .f1 = .{ .f0 = 0x123456789ABCDEF0 }, |
| 2328 | .f2 = 0x87654321, | 2360 | .f2 = 0x87654321, |
| 2329 | }; | 2361 | }; |
| 2330 | byteSwapAllFields(T, &s); | 2362 | var e: E = @fromBackingInt(0x12345678); |
| 2331 | byteSwapAllFields(K, &k); | 2363 | var f: f32 = @bitCast(@as(u32, 0x4640e400)); |
| 2332 | byteSwapAllFields(P, &p); | 2364 | byteSwap(T, &s); |
| 2333 | byteSwapAllFields(A, &a); | 2365 | byteSwap(K, &k); |
| | 2366 | byteSwap(P, &p); |
| | 2367 | byteSwap(A, &a); |
| | 2368 | byteSwap(E, &e); |
| | 2369 | byteSwap(f32, &f); |
| 2334 | try std.testing.expectEqual(T{ | 2370 | try std.testing.expectEqual(T{ |
| 2335 | .f0 = 0x12, | 2371 | .f0 = 0x12, |
| 2336 | .f1 = 0x3412, | 2372 | .f1 = 0x3412, |
| ... | @@ -2354,28 +2390,15 @@ test byteSwapAllFields { | ... | @@ -2354,28 +2390,15 @@ test byteSwapAllFields { |
| 2354 | .f1 = .{ .f0 = 0xF0DEBC9A78563412 }, | 2390 | .f1 = .{ .f0 = 0xF0DEBC9A78563412 }, |
| 2355 | .f2 = 0x21436587, | 2391 | .f2 = 0x21436587, |
| 2356 | }, a); | 2392 | }, a); |
| | 2393 | try std.testing.expectEqual(@as(E, @fromBackingInt(0x78563412)), e); |
| | 2394 | try std.testing.expectEqual(@as(f32, @bitCast(@as(u32, 0x00e44046))), f); |
| 2357 | } | 2395 | } |
| 2358 | | 2396 | |
| 2359 | /// Reverses the byte order of all elements in a slice. | 2397 | /// Reverses the byte order of all elements in a slice. |
| 2360 | /// Handles structs, unions, arrays, enums, floats, and integers recursively. | 2398 | /// Handles structs, unions, arrays, enums, floats, and integers recursively. |
| 2361 | /// Useful for converting between little-endian and big-endian representations. | 2399 | /// Useful for converting between little-endian and big-endian representations. |
| 2362 | pub fn byteSwapAllElements(comptime Elem: type, slice: []Elem) void { | 2400 | pub fn byteSwapAllElements(comptime Elem: type, slice: []Elem) void { |
| 2363 | for (slice) |*elem| { | 2401 | for (slice) |*elem| byteSwap(Elem, elem); |
| 2364 | switch (@typeInfo(@TypeOf(elem.*))) { | | |
| 2365 | .@"struct", .@"union", .array => byteSwapAllFields(@TypeOf(elem.*), elem), | | |
| 2366 | .@"enum" => { | | |
| 2367 | elem.* = @fromBackingInt(@intCast(@byteSwap(@backingInt(elem.*)))); | | |
| 2368 | }, | | |
| 2369 | .bool => {}, | | |
| 2370 | .float => |float| { | | |
| 2371 | const int_repr: @Int(.unsigned, float.bits) = @bitCast(elem.*); | | |
| 2372 | elem.* = @bitCast(@byteSwap(int_repr)); | | |
| 2373 | }, | | |
| 2374 | else => { | | |
| 2375 | elem.* = @byteSwap(elem.*); | | |
| 2376 | }, | | |
| 2377 | } | | |
| 2378 | } | | |
| 2379 | } | 2402 | } |
| 2380 | | 2403 | |
| 2381 | /// Returns an iterator that iterates over the slices of `buffer` that are not | 2404 | /// Returns an iterator that iterates over the slices of `buffer` that are not |