i’ve got a value type, let’s call it UInt8x20
, that i am using as storage for a 160-bit SHA1 git hash. the UInt8x20
stores the hash in big-endian order.
now, i am trying to add an ExpressibleByIntegerLiteral
conformance for this git hash type. after shooting myself in the foot several times, i finally got to this working implementation:
extension GitRevision:ExpressibleByIntegerLiteral
{
@inlinable public
init(integerLiteral:StaticBigInt)
{
precondition(integerLiteral.signum() >= 0,
"revision literal cannot be negative")
precondition(integerLiteral.bitWidth <= 161,
"revision literal overflows UInt8x20")
var hash:UInt8x20 = .init()
var byte:Int = hash.endIndex
var word:Int = 0
while byte != hash.startIndex
{
withUnsafeBytes(of: integerLiteral[word].bigEndian)
{
for value:UInt8 in $0.reversed()
{
byte = hash.index(before: byte)
hash[byte] = value
if byte == hash.startIndex
{
break
}
}
}
word += 1
}
self.init(hash: hash)
}
}
but this feels like a really weird implementation:
-
i’m iterating byte-by-byte, while
StaticBigInt
wants to be iterated by word (UInt
), -
i’m not using an integral number of
StaticBigInt
words (on a 64-bit system, i’m using 2.5 words), -
i’m initializing the memory from back to front, and
-
i’m checking the
byte
index bounds twice on exit.
am i holding StaticBigInt
wrong?