Set individual bytes in a uint32 using MSB 0 indexing

This commit is contained in:
Mark Spanbroek 2020-09-17 14:21:17 +02:00 committed by markspanbroek
parent d2d590ada3
commit 84ab75184c
2 changed files with 40 additions and 0 deletions

View File

@ -4,17 +4,29 @@ type
Bit* = range[0'u8..1'u8]
Bits* = distinct byte
BitIndex = BitsRange[byte]
Bytes* = distinct uint32
ByteIndex* = range[0..sizeof(uint32)-1]
proc lsb(index: BitIndex): BitsRange[byte] =
### Converts a bit index from MSB 0 to LSB 0
BitsRange[byte].high - BitsRange[byte](index)
proc lsb(index: ByteIndex): ByteIndex =
## Converts a byte index from MSB 0 to LSB 0
ByteIndex.high - index
proc `[]`*(bits: Bits, index: BitIndex): Bit =
## Returns the bit at the specified index.
## Uses MSB 0 bit numbering, so an `index`
## of 0 indicates the most significant bit.
testBit[byte](bits.byte, index.lsb).Bit
proc `[]`*(bytes: Bytes, index: ByteIndex): byte =
## Returns the byte at the specified index.
## Uses MSB 0 byte numbering, so an `index`
## of 0 indicates the most significant byte.
byte(uint32(bytes) shr (index.lsb * 8))
proc `[]=`*(bits: var Bits, index: BitIndex, value: Bit) =
## Sets the bit at the specified index.
## Uses MSB 0 bit numbering, so an `index`
@ -23,8 +35,20 @@ proc `[]=`*(bits: var Bits, index: BitIndex, value: Bit) =
of 0: clearBit[byte](bits.byte, index.lsb)
of 1: setBit[byte](bits.byte, index.lsb)
proc `[]=`*(bytes: var Bytes, index: ByteIndex, value: byte) =
## Sets the byte at the specified index.
## Uses MSB 0 byte numbering, so an `index`
## of 0 indicates the most significant byte.
bytes = Bytes(uint32(bytes) or (uint32(value) shl (index.lsb * 8)))
proc bits*(value: byte): Bits =
Bits(value)
proc bits*(value: var byte): var Bits =
Bits(value)
proc bytes*(value: uint32): Bytes =
Bytes(value)
proc bytes*(value: var uint32): var Bytes =
Bytes(value)

View File

@ -27,3 +27,19 @@ suite "bits":
value.bits[3] = 0
value.bits[7] = 0
check value == 0b01101110'u8
suite "bytes":
test "can index bytes":
let value = 0xAABBCCDD'u32
check value.bytes[0] == 0xAA
check value.bytes[1] == 0xBB
check value.bytes[2] == 0xCC
check value.bytes[3] == 0xDD
test "can set bytes":
var value = 0x00000000'u32
value.bytes[0] = 0xAA
value.bytes[2] = 0xCC
value.bytes[3] = 0xDD
check value == 0xAA00CCDD'u32