This module implements a ShiftField
type and flg
distinct type for sugar bitfields.
Useful in cases of buffer casting while working in low-level.
type
MyFlag* {.size: sizeof(cint).} = enum
A
B
C
D
MyFlags = set[MyFlag]
type MyObject = object
flags: MyFlags # no actual size info in typedesc
proc toNum(f: MyFlags): int = cast[cint](f) # what about
proc toFlags(v: int): MyFlags = cast[MyFlags](v) # other flag enums?
assert toNum({A, C}) == 5
assert toFlags(7) == {A, B, C}
From ShiftFields:
type
MyFlags* = enum
A = 0'flg
B = 1'flg
C = 2'flg
D = 3'flg
type MyObject = object
flags: ShiftField[uint16]
assert initSF[uint16]([A, C]) == 5
assert ShiftField(7).getShifts(MyFlags) == [A, B, C]
More examples:
type
Flags = enum
FlagA = 0'flg
FlagB = 1'flg
MySF = ShiftField[uint8]
NimHeader = object
magic: uint16
flags: MySF
let h = NimHeader(magic: 0'u16, flags: initSF[MySF]([FlagB]))
assert h.flags == 0b10'u8
assert not h.flags.isSet(FlagA)
if h.flags[FlagB]:
echo "(o_O) flag b is set !"
let shifts = h.flags.getShifts(Flags)
assert FlagA notin shifts
assert shifts == [FlagB]
func initShiftField*[T: SomeUnsignedInt](s: seq[enum]): ShiftField[T]
## Initializes an `ShiftField[T]` using seq `s` values for shifting.
func initSF*[T: SomeUnsignedInt](s: seq[enum]): ShiftField[T]
## Sugar alias for `initShiftField` func.
func getShifts*(sf: ShiftField, e: typedesc[enum]): seq[flg] =
## Returns `flg` typed seq of established in `sf` bits
## by `e` enum shift values.
func isSet*(sf: ShiftField, e: enum): bool
## Checks if an enum `e` bit contains in ShiftField `sf`.
func `[]`*(sf: ShiftField, e: enum): bool =
## Sugar alias for `isSet` func.
return sf.isSet(e)
iterator items*(a: openArray[flg]): uint8 =
## Base `items` iterator for flg type.
func contains*(a: openArray[flg], item: enum): bool =
## Returns true if `item` is in `a` or false if not found.
## This is a system contains **but for enum values**.
##
## This allows the `in` operator: `a.contains(item)` is the same as
## `item in a`.
proc `'flg`*(n: string): flg =
## Custom `'flg` numeric literal converter.
proc `==`*(x: openArray[flg], y: openArray[enum]): bool =
## Equality operator. Allows to compare getShifts result with flags.
❗ The getShifts
disable the HoleEnumConv
warning in proc body. If u know how to avoid this - pr welcome.