packages feed

switch-0.1.0.0: src/Device/Nintendo/Switch/Utils.hs

module Device.Nintendo.Switch.Utils where

-- attoparsec
import Data.Attoparsec.ByteString (Parser, anyWord8)

-- base
import Data.Bits ((.|.), (.&.), Bits, shiftL)
import Data.Word (Word8)

checkMask :: (Bits a, Eq a) => a -> a -> Bool
checkMask mask value =
  mask .&. value == mask

clamp :: Ord a => a -> a -> a -> a
clamp low high value
  | value <= low  = low
  | value >= high = high
  | otherwise     = value

combine :: Word8 -> Word8 -> Word8
combine high low =
  shiftL high 4 .|. low

pairs :: [a] -> [(a,a)]
pairs (x:y:rest) = (x,y) : pairs rest
pairs _ = []

discretize :: (Real a, Integral b) => a -> a -> b -> b -> a -> b
discretize srcMin srcMax tgtMin tgtMax value
  | value <= srcMin = tgtMin
  | value >= srcMax = tgtMax
  | otherwise = round $ fromIntegral tgtMin + frac * fromIntegral (tgtMax - tgtMin)
  where
    frac = (realToFrac (value - srcMin) / realToFrac (srcMax - srcMin)) :: Float

tripleZipWith :: (a -> b -> c) -> (a, a, a) -> (b, b, b) -> (c, c, c)
tripleZipWith f (a1, a2, a3) (b1, b2, b3) = (f a1 b1, f a2 b2, f a3 b3)

tripleMap :: (a -> b) -> (a, a, a) -> (b, b, b)
tripleMap f (a1, a2, a3) = (f a1, f a2, f a3)

littleEndianWord16Parser :: (Bits a, Num a) => Parser a
littleEndianWord16Parser = do
  byte0 <- fromIntegral <$> anyWord8
  byte1 <- fromIntegral <$> anyWord8
  pure $ shiftL byte1 8 .|. byte0

tripleParser :: (Bits a, Num a) => Parser (a, a, a)
tripleParser = do
  x <- littleEndianWord16Parser
  y <- littleEndianWord16Parser
  z <- littleEndianWord16Parser
  pure (x, y, z)