module Data.FlagSet.PackedRecord (
getIntByMask, putIntByMask, accessorIntByMask,
getIntByRange, putIntByRange, accessorIntByRange,
) where
import Data.FlagSet (T(Cons), Mask(Mask), )
import qualified Data.Bits as B
import Data.Bits (Bits, (.&.), (.|.), )
import qualified Data.Accessor.Basic as Acc
import Data.EnumSet.Utility ((.-.), )
leastSigBit :: (Num w, Bits w) => w -> w
leastSigBit m = (-m) .&. m
getIntByMask ::
(Bits w, Integral w, Integral i) =>
Mask w a b -> T w a -> i
getIntByMask (Mask m) (Cons fs) =
fromIntegral $ div (m .&. fs) (leastSigBit m)
putIntByMask ::
(Bits w, Integral w, Integral i) =>
Mask w a b -> i -> T w a -> T w a
putIntByMask (Mask m) i (Cons fs) =
Cons $ (fs .-. m) .|. (fromIntegral i * leastSigBit m)
accessorIntByMask ::
(Bits w, Integral w, Integral i) =>
Mask w a b -> Acc.T (T w a) i
accessorIntByMask m =
Acc.fromSetGet (putIntByMask m) (getIntByMask m)
maskFromNumber ::
(Num w, Bits w) =>
Int -> w
maskFromNumber number =
B.shiftL 1 number - 1
getIntByRange ::
(Bits w, Integral w, Integral i) =>
Int -> Int -> T w a -> i
getIntByRange number start (Cons fs) =
fromIntegral $ B.shiftR fs start .&. maskFromNumber number
putIntByRange ::
(Bits w, Integral w, Integral i) =>
Int -> Int -> i -> T w a -> T w a
putIntByRange number start i (Cons fs) =
Cons $
(fs .-. B.shiftL (maskFromNumber number) start)
.|.
B.shiftL (fromIntegral i) start
accessorIntByRange ::
(Bits w, Integral w, Integral i) =>
Int -> Int -> Acc.T (T w a) i
accessorIntByRange number start =
Acc.fromSetGet (putIntByRange number start) (getIntByRange number start)