Skip to content

Commit 15b0b2a

Browse files
authored
Fix floating point printing (#13)
This PR fixes printer intel implementation of floating point, which always yields little endian instead of big endian.
1 parent d863f80 commit 15b0b2a

File tree

4 files changed

+95
-14
lines changed

4 files changed

+95
-14
lines changed

Sources/BinaryParseKit/CustomExtensions.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ public protocol ExpressibleByBitPattern {
2121
///
2222
/// - Parameter bitPattern: The bit pattern to interpret as this type
2323
init(bitPattern: BitPattern)
24+
25+
var bitPattern: BitPattern { get }
2426
}
2527

2628
extension Float16: ExpressibleByBitPattern {}

Sources/BinaryParseKit/Printer/PrintableExtensions.swift

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,27 @@ extension UInt16: Printable {}
2929
extension UInt32: Printable {}
3030
extension UInt: Printable {}
3131
extension UInt64: Printable {}
32-
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
3332
extension UInt128: Printable {}
3433

3534
extension Int8: Printable {}
3635
extension Int16: Printable {}
3736
extension Int32: Printable {}
3837
extension Int: Printable {}
3938
extension Int64: Printable {}
40-
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
4139
extension Int128: Printable {}
4240

4341
// MARK: - Floating Point
4442

45-
extension BinaryFloatingPoint {
46-
func toBytes() -> [UInt8] {
47-
unsafe withUnsafeBytes(of: self, Array.init)
43+
extension ExpressibleByBitPattern {
44+
func toBytes(useBigEndian: Bool = true) -> [UInt8] {
45+
unsafe withUnsafeBytes(
46+
of: useBigEndian ? bitPattern.bigEndian : bitPattern.littleEndian,
47+
Array.init,
48+
)
4849
}
4950
}
5051

51-
public extension Printable where Self: BinaryFloatingPoint {
52+
public extension Printable where Self: ExpressibleByBitPattern {
5253
func printerIntel() -> PrinterIntel {
5354
.builtIn(
5455
.init(bytes: toBytes()),

Tests/BinaryParseKitTests/TestBinaryFloatingPoint.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,45 +16,45 @@ extension Endianness: @unchecked @retroactive Sendable {}
1616
struct TestBinaryFloatingPoint {
1717
@Test
1818
func parsingFromByteArray() throws {
19-
try testingImpl(
19+
try testingParsingImpl(
2020
[0xDE, 0xAD, 0xBE, 0xEF],
2121
to: Float16.self,
2222
endianness: .big,
2323
expected: .init(bitPattern: 0xDEAD),
2424
)
25-
try testingImpl(
25+
try testingParsingImpl(
2626
[0xDE, 0xAD, 0xBE, 0xEF],
2727
to: Float16.self,
2828
endianness: .little,
2929
expected: .init(bitPattern: 0xADDE),
3030
)
31-
try testingImpl(
31+
try testingParsingImpl(
3232
[0xDE, 0xAD, 0xBE, 0xEF],
3333
to: Float.self,
3434
endianness: .big,
3535
expected: .init(bitPattern: 0xDEAD_BEEF),
3636
)
37-
try testingImpl(
37+
try testingParsingImpl(
3838
[0xDE, 0xAD, 0xBE, 0xEF],
3939
to: Float.self,
4040
endianness: .little,
4141
expected: .init(bitPattern: 0xEFBE_ADDE),
4242
)
43-
try testingImpl(
43+
try testingParsingImpl(
4444
[0xAB, 0xAD, 0xCA, 0xFE, 0xAA, 0xC0, 0xFF, 0xEE],
4545
to: Double.self,
4646
endianness: .big,
4747
expected: .init(bitPattern: 0xABAD_CAFE_AAC0_FFEE),
4848
)
49-
try testingImpl(
49+
try testingParsingImpl(
5050
[0xAB, 0xAD, 0xCA, 0xFE, 0xAA, 0xC0, 0xFF, 0xEE],
5151
to: Double.self,
5252
endianness: .little,
5353
expected: .init(bitPattern: 0xEEFF_C0AA_FECA_ADAB),
5454
)
5555
}
5656

57-
func testingImpl<T: EndianParsable & BinaryFloatingPoint>(
57+
func testingParsingImpl<T: EndianParsable & BinaryFloatingPoint>(
5858
_ data: [UInt8],
5959
to _: T.Type,
6060
endianness: Endianness,

Tests/BinaryParseKitTests/TestPrinterIntel.swift

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,91 @@
55
// Created by Larry Zeng on 11/17/25.
66
//
77

8-
import BinaryParseKit
8+
@testable import BinaryParseKit
99
import BinaryParsing
1010
import Foundation
1111
import Testing
1212

1313
@Suite
1414
struct PrinterIntelTest {
15+
// MARK: - Builtin PrinterIntel Generation
16+
17+
@Test
18+
func `floating point printer intel`() {
19+
// Float16
20+
#expect(Float16(bitPattern: 0xDEAD).toBytes(useBigEndian: true) == [0xDE, 0xAD])
21+
#expect(Float16(bitPattern: 0xDEAD).toBytes(useBigEndian: false) == [0xAD, 0xDE])
22+
23+
// Float
24+
#expect(Float(bitPattern: 0xDEAD_BEEF).toBytes(useBigEndian: true) == [0xDE, 0xAD, 0xBE, 0xEF])
25+
#expect(Float(bitPattern: 0xDEAD_BEEF).toBytes(useBigEndian: false) == [0xEF, 0xBE, 0xAD, 0xDE])
26+
27+
// Double
28+
#expect(
29+
Double(bitPattern: 0xABAD_CAFE_AAC0_FFEE).toBytes(useBigEndian: true)
30+
== [0xAB, 0xAD, 0xCA, 0xFE, 0xAA, 0xC0, 0xFF, 0xEE],
31+
)
32+
#expect(
33+
Double(bitPattern: 0xABAD_CAFE_AAC0_FFEE).toBytes(useBigEndian: false)
34+
== [0xEE, 0xFF, 0xC0, 0xAA, 0xFE, 0xCA, 0xAD, 0xAB],
35+
)
36+
}
37+
38+
@Test
39+
func `integer printer intel`() {
40+
// Int8/UInt8
41+
#expect(Int8(bitPattern: 0xAB).toBytes(useBigEndian: true) == [0xAB])
42+
#expect(UInt8(0xAB).toBytes(useBigEndian: false) == [0xAB])
43+
44+
// Int16/UInt16
45+
#expect(Int16(bitPattern: 0xDEAD).toBytes(useBigEndian: true) == [0xDE, 0xAD])
46+
#expect(Int16(bitPattern: 0xDEAD).toBytes(useBigEndian: false) == [0xAD, 0xDE])
47+
#expect(UInt16(0xBEEF).toBytes(useBigEndian: true) == [0xBE, 0xEF])
48+
#expect(UInt16(0xBEEF).toBytes(useBigEndian: false) == [0xEF, 0xBE])
49+
50+
// Int32/UInt32
51+
#expect(Int32(bitPattern: 0xDEAD_BEEF).toBytes(useBigEndian: true) == [0xDE, 0xAD, 0xBE, 0xEF])
52+
#expect(Int32(bitPattern: 0xDEAD_BEEF).toBytes(useBigEndian: false) == [0xEF, 0xBE, 0xAD, 0xDE])
53+
#expect(UInt32(0xCAFE_BABE).toBytes(useBigEndian: true) == [0xCA, 0xFE, 0xBA, 0xBE])
54+
#expect(UInt32(0xCAFE_BABE).toBytes(useBigEndian: false) == [0xBE, 0xBA, 0xFE, 0xCA])
55+
56+
// Int64/UInt64
57+
#expect(
58+
Int64(bitPattern: 0xDEAD_BEEF_CAFE_BABE).toBytes(useBigEndian: true)
59+
== [0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE],
60+
)
61+
#expect(
62+
Int64(bitPattern: 0xDEAD_BEEF_CAFE_BABE).toBytes(useBigEndian: false)
63+
== [0xBE, 0xBA, 0xFE, 0xCA, 0xEF, 0xBE, 0xAD, 0xDE],
64+
)
65+
#expect(
66+
UInt64(0xABAD_CAFE_AAC0_FFEE).toBytes(useBigEndian: true)
67+
== [0xAB, 0xAD, 0xCA, 0xFE, 0xAA, 0xC0, 0xFF, 0xEE],
68+
)
69+
#expect(
70+
UInt64(0xABAD_CAFE_AAC0_FFEE).toBytes(useBigEndian: false)
71+
== [0xEE, 0xFF, 0xC0, 0xAA, 0xFE, 0xCA, 0xAD, 0xAB],
72+
)
73+
74+
// Int128/UInt128
75+
#expect(
76+
Int128(bitPattern: 0xDEAD_BEEF_CAFE_BABE_1234_5678_9ABC_DEF0).toBytes(useBigEndian: true)
77+
== [0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0],
78+
)
79+
#expect(
80+
Int128(bitPattern: 0xDEAD_BEEF_CAFE_BABE_1234_5678_9ABC_DEF0).toBytes(useBigEndian: false)
81+
== [0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, 0xBE, 0xBA, 0xFE, 0xCA, 0xEF, 0xBE, 0xAD, 0xDE],
82+
)
83+
#expect(
84+
UInt128(0xABAD_CAFE_AAC0_FFEE_1122_3344_5566_7788).toBytes(useBigEndian: true)
85+
== [0xAB, 0xAD, 0xCA, 0xFE, 0xAA, 0xC0, 0xFF, 0xEE, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88],
86+
)
87+
#expect(
88+
UInt128(0xABAD_CAFE_AAC0_FFEE_1122_3344_5566_7788).toBytes(useBigEndian: false)
89+
== [0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0xEE, 0xFF, 0xC0, 0xAA, 0xFE, 0xCA, 0xAD, 0xAB],
90+
)
91+
}
92+
1593
// MARK: - ParseEnum PrinterIntel Tests
1694

1795
@ParseEnum

0 commit comments

Comments
 (0)