7. Enums¶
If you have a C enum (or a set of #define’s) with consecutive values and starting from 0, you can do:
{-# LANGUAGE DeriveAnyClass #-}
import Haskus.Format.Binary.Enum
data MyEnum
= MyEnumX
| MyEnumY
| MyEnumZ
deriving (Show,Eq,Enum,CEnum)
If the values are not consecutive or don’t start from 0, you can write your own
CEnum
instance:
-- Add 1 to the enum number to get the valid value
instance CEnum MyEnum where
fromCEnum = (+1) . fromIntegral . fromEnum
toCEnum = toEnum . (\x -> x-1) . fromIntegral
To use an Enum as a field in a structure, use EnumField
:
data StructZ = StructZ
{ zField0 :: StructX
, zField1 :: EnumField Word32 MyEnum
} deriving (Show,Generic,Storable)
The first type parameter of EnumField
indicates the backing word type (i.e. the
size of the field in the structure). For instance, you can use Word8, Word16,
Word32 and Word64.
To create or extract an EnumField
, use the methods:
fromEnumField :: CEnum a => EnumField b a -> a
toEnumField :: CEnum a => a -> EnumField b a
We use a CEnum class that is very similar to Enum because Enum is a special
class that has access to data constructor tags. If we redefine Enum, we cannot
use fromEnum
to get the data constructor tag.