packages feed

byteslice-0.2.15.0: src/Data/Bytes/Internal/Show.hs

{-# LANGUAGE BangPatterns #-}

module Data.Bytes.Internal.Show
  ( showsSlice
  ) where

import Data.Bits (unsafeShiftR, (.&.))
import Data.Char (ord)
import Data.Primitive (ByteArray)
import Data.Word (Word8)
import GHC.Base (unsafeChr)

import qualified Data.Primitive as PM

showsSlice :: ByteArray -> Int -> Int -> String -> String
showsSlice arr off len s =
  if len == 0
    then showString "[]" s
    else
      showString "[0x" $
        showHexDigitsWord8 (PM.indexByteArray arr off) $
          showHexLoop (off + 1) (len - 1) arr $
            showChar ']' $
              s

showHexLoop :: Int -> Int -> ByteArray -> String -> String
showHexLoop !ix !len !arr s =
  if len > 0
    then ',' : '0' : 'x' : showHexDigitsWord8 (PM.indexByteArray arr ix) (showHexLoop (ix + 1) (len - 1) arr s)
    else s

showHexDigitsWord8 :: Word8 -> String -> String
showHexDigitsWord8 !w s = word4ToChar (unsafeShiftR w 4) : word4ToChar (0x0F .&. w) : s

word4ToChar :: Word8 -> Char
word4ToChar w =
  if w < 10
    then unsafeChr (ord '0' + fromIntegral w)
    else unsafeChr (ord 'a' + (fromIntegral w) - 10)