{-# LANGUAGE TypeFamilies #-}

module Data.Avro.Internal.Zag
  ( Zag(..)
  ) where

import Data.Bits
import Data.Int
import Data.Word

class Zag a where
  type Zagged a
  zag :: a -> Zagged a

instance Zag Word8 where
  type Zagged Word8 = Int8
  zag :: Word8 -> Zagged Word8
zag Word8
n = Word8 -> Int8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> Int8) -> Word8 -> Int8
forall a b. (a -> b) -> a -> b
$ (Word8
n Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`shiftR` Int
1) Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
`xor` Word8 -> Word8
forall a. Num a => a -> a
negate (Word8
n Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0x1)
  {-# INLINE zag #-}

instance Zag Word16 where
  type Zagged Word16 = Int16
  zag :: Word16 -> Zagged Word16
zag Word16
n = Word16 -> Int16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word16 -> Int16) -> Word16 -> Int16
forall a b. (a -> b) -> a -> b
$ (Word16
n Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
`shiftR` Int
1) Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
`xor` Word16 -> Word16
forall a. Num a => a -> a
negate (Word16
n Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.&. Word16
0x1)
  {-# INLINE zag #-}

instance Zag Word32 where
  type Zagged Word32 = Int32
  zag :: Word32 -> Zagged Word32
zag Word32
n = Word32 -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Int32) -> Word32 -> Int32
forall a b. (a -> b) -> a -> b
$ (Word32
n Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftR` Int
1) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
`xor` Word32 -> Word32
forall a. Num a => a -> a
negate (Word32
n Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
0x1)
  {-# INLINE zag #-}

instance Zag Word64 where
  type Zagged Word64 = Int64
  zag :: Word64 -> Zagged Word64
zag Word64
n = Word64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int64) -> Word64 -> Int64
forall a b. (a -> b) -> a -> b
$ (Word64
n Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftR` Int
1) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
`xor` Word64 -> Word64
forall a. Num a => a -> a
negate (Word64
n Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
0x1)
  {-# INLINE zag #-}

instance Zag Word where
  type Zagged Word = Int
  zag :: Word -> Zagged Word
zag Word
n = Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word -> Int) -> Word -> Int
forall a b. (a -> b) -> a -> b
$ (Word
n Word -> Int -> Word
forall a. Bits a => a -> Int -> a
`shiftR` Int
1) Word -> Word -> Word
forall a. Bits a => a -> a -> a
`xor` Word -> Word
forall a. Num a => a -> a
negate (Word
n Word -> Word -> Word
forall a. Bits a => a -> a -> a
.&. Word
0x1)
  {-# INLINE zag #-}