From a588edc4cd5ec5a0c3c7d2155495bc04745db253 Mon Sep 17 00:00:00 2001 From: Paul Backus Date: Thu, 27 Feb 2025 14:34:42 -0500 Subject: [PATCH 1/2] Add std.conv.bitCast This helper function is a more readable alternative to the traditional pointer-cast-based syntax for reinterpreting casts. The name bitCast is used for this operation in several other languages, including C++ [1], Swift [2], C# [3], Zig [4], and LLVM IR [5]. [1] https://en.cppreference.com/w/cpp/numeric/bit_cast [2] https://developer.apple.com/documentation/swift/unsafebitcast(_:to:) [3] https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.unsafe.bitcast [4] https://ziglang.org/documentation/0.10.0/#bitCast [5] https://llvm.org/docs/LangRef.html#bitcast-to-instruction --- std/conv.d | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/std/conv.d b/std/conv.d index 5e0165cb609..65042b81095 100644 --- a/std/conv.d +++ b/std/conv.d @@ -13,6 +13,7 @@ $(TR $(TD Generic) $(TD $(LREF parse) $(LREF to) $(LREF toChars) + $(LREF bitCast) )) $(TR $(TD Strings) $(TD $(LREF text) @@ -6047,3 +6048,38 @@ package enum toCtString(ulong n) = n.stringof[0 .. $ - "LU".length]; assert(toCtString!0 == "0"); assert(toCtString!123456 == "123456"); } + +/** + * Takes the raw bits of a value and reinterprets them as a different type. + * + * Params: + * T = the new type. + * value = the value to reinterpret. + * + * Returns: a reference to the reinterpreted value. + */ +pragma(inline, true) +ref T bitCast(T, S)(ref S value) +if (T.sizeof <= S.sizeof) +{ + return *cast(T*) &value; +} + +/// +@safe unittest +{ + uint n = 0xDEADBEEF; + + version (LittleEndian) + assert(n.bitCast!(ubyte[4]) == [0xEF, 0xBE, 0xAD, 0xDE]); + version (BigEndian) + assert(n.bitCast!(ubyte[4]) == [0xDE, 0xAD, 0xBE, 0xEF]); +} + +// Sizes must be compatible +@safe unittest +{ + uint n; + + assert(!__traits(compiles, n.bitCast!ulong)); +} From c33a31988fc81c4e7420ddd28bd012902ad5e16e Mon Sep 17 00:00:00 2001 From: Paul Backus Date: Fri, 28 Feb 2025 07:52:58 -0500 Subject: [PATCH 2/2] Add changelog entry for std.conv.bitCast --- changelog/bit-cast.dd | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 changelog/bit-cast.dd diff --git a/changelog/bit-cast.dd b/changelog/bit-cast.dd new file mode 100644 index 00000000000..11333d2b9c6 --- /dev/null +++ b/changelog/bit-cast.dd @@ -0,0 +1,14 @@ +Added `std.conv.bitCast` + +This convenience function allows reinterpreting casts to be written in a more +readable way. + +--- +uint n = 0xDEADBEEF; + +// Before +writeln("Bytes of n are: ", *cast(const ubyte[4]*) &n); + +// After +writeln("Bytes of n are: ", n.bitCast!(const ubyte[4])); +---