haskell / haskell/c2hs

Generate an enum that supports Bits instances

Open
#235 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Haskell
Stars
211
Forks
52
PR merge metrics
No merged PRs in 30d

Description

First of all let me apologize if this is not the correct place to post (as my issue is a priori not with the c2hs software).
I have a TcpState data structure generated by c2hs via `{#enum TCP_ESTABLISHED as TcpState {underscoreToCase} deriving (Eq, Show)#}`.
which generates (from the linux headers)
```
data TcpState = TcpEstablished
| TcpSynSent
| TcpSynRecv
| TcpFinWait1
| TcpFinWait2
| TcpTimeWait
| TcpClose
| TcpCloseWait
| TcpLastAck
| TcpListen
| TcpClosing
| TcpNewSynRecv
| TcpMaxStates
deriving (Eq,Show)
instance Enum TcpState where
succ TcpEstablished = TcpSynSent
succ TcpSynSent = TcpSynRecv
succ TcpSynRecv = TcpFinWait1
succ TcpFinWait1 = TcpFinWait2
succ TcpFinWait2 = TcpTimeWait
succ TcpTimeWait = TcpClose
succ TcpClose = TcpCloseWait
succ TcpCloseWait = TcpLastAck
succ TcpLastAck = TcpListen
succ TcpListen = TcpClosing
succ TcpClosing = TcpNewSynRecv
succ TcpNewSynRecv = TcpMaxStates
succ TcpMaxStates = error "TcpState.succ: TcpMaxStates has no successor"

pred TcpSynSent = TcpEstablished
pred TcpSynRecv = TcpSynSent
pred TcpFinWait1 = TcpSynRecv
pred TcpFinWait2 = TcpFinWait1
pred TcpTimeWait = TcpFinWait2
pred TcpClose = TcpTimeWait
pred TcpCloseWait = TcpClose
pred TcpLastAck = TcpCloseWait
pred TcpListen = TcpLastAck
pred TcpClosing = TcpListen
pred TcpNewSynRecv = TcpClosing
pred TcpMaxStates = TcpNewSynRecv
pred TcpEstablished = error "TcpState.pred: TcpEstablished has no predecessor"

enumFromTo from to = go from
where
end = fromEnum to
go v = case compare (fromEnum v) end of
LT -> v : go (succ v)
EQ -> [v]
GT -> []

enumFrom from = enumFromTo from TcpMaxStates

fromEnum TcpEstablished = 1
fromEnum TcpSynSent = 2
fromEnum TcpSynRecv = 3
fromEnum TcpFinWait1 = 4
fromEnum TcpFinWait2 = 5
fromEnum TcpTimeWait = 6
fromEnum TcpClose = 7
fromEnum TcpCloseWait = 8
fromEnum TcpLastAck = 9
fromEnum TcpListen = 10
fromEnum TcpClosing = 11
fromEnum TcpNewSynRecv = 12
fromEnum TcpMaxStates = 13

toEnum 1 = TcpEstablished
toEnum 2 = TcpSynSent
toEnum 3 = TcpSynRecv
toEnum 4 = TcpFinWait1
toEnum 5 = TcpFinWait2
toEnum 6 = TcpTimeWait
toEnum 7 = TcpClose
toEnum 8 = TcpCloseWait
toEnum 9 = TcpLastAck
toEnum 10 = TcpListen
toEnum 11 = TcpClosing
toEnum 12 = TcpNewSynRecv
toEnum 13 = TcpMaxStates
toEnum unmatched = error ("TcpState.toEnum: Cannot match " ++ show unmatched)
```

I would like to add Data.Bits instance to TcpState so that I can write `TcpEstablished .|. TcpListen`.
I've tried to derive Bits in
`{#enum TCP_ESTABLISHED as TcpState {underscoreToCase} deriving (Eq, Show, Bits)#}`
but it generates:
```
Generated.chs:43:21: error:
• Can't make a derived instance of ‘Bits TcpState’:
‘Bits’ is not a stock derivable class (Eq, Show, etc.)
Try enabling DeriveAnyClass
```
I believe I could hack something together but as it seems like a common usecase. I wondered if there weren't some trick I could use straight from c2hs (could not find it on the wiki).

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.