module Data.FlagSet (
T(Cons, decons),
fromMaskedValue, match,
Enum(fromEnum),
compose, decompose,
Mask(Mask, unmask), maskValue,
Value(Value, unvalue),
MaskedValue(MaskedValue),
get, put, accessor,
) where
import Data.Bits (Bits, (.&.), (.|.), )
import Data.Monoid (Monoid(mempty, mappend, mconcat), )
import Data.Semigroup (Semigroup((<>)), )
import qualified Foreign.Storable.Newtype as Store
import Foreign.Storable (Storable(sizeOf, alignment, peek, poke), )
import qualified Data.Accessor.Basic as Acc
import Data.EnumSet.Utility (empty, (.-.), )
import qualified Prelude as P
import Prelude hiding (Enum, fromEnum, toEnum, null, flip, )
newtype T word a = Cons {decons :: word}
deriving (Eq)
instance (Storable w) => Storable (T w a) where
sizeOf = Store.sizeOf decons
alignment = Store.alignment decons
peek = Store.peek Cons
poke = Store.poke decons
newtype Mask w a b = Mask {unmask :: w}
deriving (Eq, Show)
newtype Value w b = Value {unvalue :: w}
deriving (Eq, Show)
get :: (Enum a, Bits w) => Mask w a b -> T w a -> Value w b
get (Mask m) (Cons fs) = Value (m .&. fs)
put :: (Enum a, Bits w) => Mask w a b -> Value w b -> T w a -> T w a
put (Mask m) (Value v) (Cons fs) =
Cons $ (fs .-. m) .|. v
accessor :: (Enum a, Bits w) => Mask w a b -> Acc.T (T w a) (Value w b)
accessor m = Acc.fromSetGet (put m) (get m)
data MaskedValue w a = MaskedValue w w
deriving (Eq, Show)
fromMaskedValue :: MaskedValue w a -> T w a
fromMaskedValue (MaskedValue _m v) = Cons v
match :: (Bits w) => T w a -> MaskedValue w a -> Bool
match (Cons fs) (MaskedValue m v) =
m .&. fs == v
maskValue :: Mask w a b -> Value w b -> MaskedValue w a
maskValue (Mask m) (Value v) = MaskedValue m v
instance (Bits w) => Semigroup (MaskedValue w a) where
MaskedValue mx vx <> MaskedValue my vy =
MaskedValue (mx .|. my) (vx .-. my .|. vy)
instance (Bits w) => Monoid (MaskedValue w a) where
mempty = MaskedValue empty empty
mappend = (<>)
class Enum a where
fromEnum :: (Bits w) => a -> MaskedValue w a
decompose :: (Bounded a, Enum a, P.Enum a, Bits w) => T w a -> [a]
decompose x =
filter (match x . fromEnum) [minBound .. maxBound]
compose :: (Enum a, P.Enum a, Bits w) => [a] -> T w a
compose xs =
fromMaskedValue $ mconcat $ map fromEnum xs