packages feed

gbnet-hs-0.1.0.0: src/GBNet/Types.hs

{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

-- |
-- Module      : GBNet.Types
-- Description : Domain-specific newtypes for type safety
--
-- Wraps raw primitives in newtypes so the compiler catches type mix-ups
-- at compile time. Zero runtime cost via newtype erasure.
module GBNet.Types
  ( -- * Channel identifier
    ChannelId (..),
    channelIdToInt,

    -- * Sequence number
    SequenceNum (..),

    -- * Message identifier
    MessageId (..),
  )
where

import Control.DeepSeq (NFData)
import Data.Word (Word16, Word32, Word8)
import Foreign.Storable (Storable (..))

-- | Channel identifier (stored as Word8).
-- Not a quantity — no 'Num' instance. Construct via @ChannelId 0@.
newtype ChannelId = ChannelId {unChannelId :: Word8}
  deriving stock (Eq, Ord, Show)
  deriving newtype (Bounded, NFData, Storable)

-- | Convert a 'ChannelId' to 'Int' for IntMap indexing.
channelIdToInt :: ChannelId -> Int
channelIdToInt = fromIntegral . unChannelId
{-# INLINE channelIdToInt #-}

-- | Sequence number with Word16 wraparound arithmetic.
-- Derives 'Num' because @seq + 1@ is the canonical operation.
newtype SequenceNum = SequenceNum {unSequenceNum :: Word16}
  deriving stock (Eq, Ord, Show)
  deriving newtype (Bounded, Enum, Integral, NFData, Num, Real, Storable)

-- | Fragment message identifier.
-- Derives 'Num' for increment patterns in fragmentation.
newtype MessageId = MessageId {unMessageId :: Word32}
  deriving stock (Eq, Ord, Show)
  deriving newtype (Bounded, NFData, Num, Storable)