{-# LANGUAGE DeriveDataTypeable #-}

module Data.Word128 (
    -- * Definition
    Word128 -- opaque
    -- * Construction
  , word128
    -- * Destruction
  , word128MS64
  , word128LS64
  ) where

import Data.Bits
import Data.Data
import Data.Ix
import Data.Word
import Foreign
import GHC.Generics

import qualified Data.WideWord.Word128 as WW

import Codec.Borsh.Internal.Util.ByteSwap (ByteSwap(..))

{-------------------------------------------------------------------------------
  Definition, construction, destruction
-------------------------------------------------------------------------------}

-- | Unsigned 128-bit word
--
-- Implementation note: this currently relies on the implementation of the
-- [wide-word](https://hackage.haskell.org/package/wide-word) package, with some
-- additional instances. However, the use of @wide-word@ is not part of the
-- public API of the @borsh@ package.
newtype Word128 = Word128 WW.Word128
  deriving stock Typeable Word128
Word128 -> DataType
Word128 -> Constr
(forall b. Data b => b -> b) -> Word128 -> Word128
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Word128 -> u
forall u. (forall d. Data d => d -> u) -> Word128 -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Word128 -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Word128 -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Word128 -> m Word128
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Word128 -> m Word128
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Word128
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Word128 -> c Word128
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Word128)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Word128)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Word128 -> m Word128
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Word128 -> m Word128
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Word128 -> m Word128
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Word128 -> m Word128
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Word128 -> m Word128
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Word128 -> m Word128
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Word128 -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Word128 -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> Word128 -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Word128 -> [u]
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Word128 -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Word128 -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Word128 -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Word128 -> r
gmapT :: (forall b. Data b => b -> b) -> Word128 -> Word128
$cgmapT :: (forall b. Data b => b -> b) -> Word128 -> Word128
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Word128)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Word128)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Word128)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Word128)
dataTypeOf :: Word128 -> DataType
$cdataTypeOf :: Word128 -> DataType
toConstr :: Word128 -> Constr
$ctoConstr :: Word128 -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Word128
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Word128
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Word128 -> c Word128
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Word128 -> c Word128
Data
  deriving newtype (
      Eq Word128
Word128
Int -> Word128
Word128 -> Bool
Word128 -> Int
Word128 -> Maybe Int
Word128 -> Word128
Word128 -> Int -> Bool
Word128 -> Int -> Word128
Word128 -> Word128 -> Word128
forall a.
Eq a
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> a
-> (Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> Bool)
-> (a -> Maybe Int)
-> (a -> Int)
-> (a -> Bool)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int)
-> Bits a
popCount :: Word128 -> Int
$cpopCount :: Word128 -> Int
rotateR :: Word128 -> Int -> Word128
$crotateR :: Word128 -> Int -> Word128
rotateL :: Word128 -> Int -> Word128
$crotateL :: Word128 -> Int -> Word128
unsafeShiftR :: Word128 -> Int -> Word128
$cunsafeShiftR :: Word128 -> Int -> Word128
shiftR :: Word128 -> Int -> Word128
$cshiftR :: Word128 -> Int -> Word128
unsafeShiftL :: Word128 -> Int -> Word128
$cunsafeShiftL :: Word128 -> Int -> Word128
shiftL :: Word128 -> Int -> Word128
$cshiftL :: Word128 -> Int -> Word128
isSigned :: Word128 -> Bool
$cisSigned :: Word128 -> Bool
bitSize :: Word128 -> Int
$cbitSize :: Word128 -> Int
bitSizeMaybe :: Word128 -> Maybe Int
$cbitSizeMaybe :: Word128 -> Maybe Int
testBit :: Word128 -> Int -> Bool
$ctestBit :: Word128 -> Int -> Bool
complementBit :: Word128 -> Int -> Word128
$ccomplementBit :: Word128 -> Int -> Word128
clearBit :: Word128 -> Int -> Word128
$cclearBit :: Word128 -> Int -> Word128
setBit :: Word128 -> Int -> Word128
$csetBit :: Word128 -> Int -> Word128
bit :: Int -> Word128
$cbit :: Int -> Word128
zeroBits :: Word128
$czeroBits :: Word128
rotate :: Word128 -> Int -> Word128
$crotate :: Word128 -> Int -> Word128
shift :: Word128 -> Int -> Word128
$cshift :: Word128 -> Int -> Word128
complement :: Word128 -> Word128
$ccomplement :: Word128 -> Word128
xor :: Word128 -> Word128 -> Word128
$cxor :: Word128 -> Word128 -> Word128
.|. :: Word128 -> Word128 -> Word128
$c.|. :: Word128 -> Word128 -> Word128
.&. :: Word128 -> Word128 -> Word128
$c.&. :: Word128 -> Word128 -> Word128
Bits
    , Word128
forall a. a -> a -> Bounded a
maxBound :: Word128
$cmaxBound :: Word128
minBound :: Word128
$cminBound :: Word128
Bounded
    , Int -> Word128
Word128 -> Int
Word128 -> [Word128]
Word128 -> Word128
Word128 -> Word128 -> [Word128]
Word128 -> Word128 -> Word128 -> [Word128]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Word128 -> Word128 -> Word128 -> [Word128]
$cenumFromThenTo :: Word128 -> Word128 -> Word128 -> [Word128]
enumFromTo :: Word128 -> Word128 -> [Word128]
$cenumFromTo :: Word128 -> Word128 -> [Word128]
enumFromThen :: Word128 -> Word128 -> [Word128]
$cenumFromThen :: Word128 -> Word128 -> [Word128]
enumFrom :: Word128 -> [Word128]
$cenumFrom :: Word128 -> [Word128]
fromEnum :: Word128 -> Int
$cfromEnum :: Word128 -> Int
toEnum :: Int -> Word128
$ctoEnum :: Int -> Word128
pred :: Word128 -> Word128
$cpred :: Word128 -> Word128
succ :: Word128 -> Word128
$csucc :: Word128 -> Word128
Enum
    , Word128 -> Word128 -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Word128 -> Word128 -> Bool
$c/= :: Word128 -> Word128 -> Bool
== :: Word128 -> Word128 -> Bool
$c== :: Word128 -> Word128 -> Bool
Eq
    , Bits Word128
Word128 -> Int
forall b.
Bits b -> (b -> Int) -> (b -> Int) -> (b -> Int) -> FiniteBits b
countTrailingZeros :: Word128 -> Int
$ccountTrailingZeros :: Word128 -> Int
countLeadingZeros :: Word128 -> Int
$ccountLeadingZeros :: Word128 -> Int
finiteBitSize :: Word128 -> Int
$cfiniteBitSize :: Word128 -> Int
FiniteBits
    , forall x. Rep Word128 x -> Word128
forall x. Word128 -> Rep Word128 x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
to :: forall x. Rep Word128 x -> Word128
$cto :: forall x. Rep Word128 x -> Word128
from :: forall x. Word128 -> Rep Word128 x
$cfrom :: forall x. Word128 -> Rep Word128 x
Generic
    , Enum Word128
Real Word128
Word128 -> Integer
Word128 -> Word128 -> (Word128, Word128)
Word128 -> Word128 -> Word128
forall a.
Real a
-> Enum a
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
toInteger :: Word128 -> Integer
$ctoInteger :: Word128 -> Integer
divMod :: Word128 -> Word128 -> (Word128, Word128)
$cdivMod :: Word128 -> Word128 -> (Word128, Word128)
quotRem :: Word128 -> Word128 -> (Word128, Word128)
$cquotRem :: Word128 -> Word128 -> (Word128, Word128)
mod :: Word128 -> Word128 -> Word128
$cmod :: Word128 -> Word128 -> Word128
div :: Word128 -> Word128 -> Word128
$cdiv :: Word128 -> Word128 -> Word128
rem :: Word128 -> Word128 -> Word128
$crem :: Word128 -> Word128 -> Word128
quot :: Word128 -> Word128 -> Word128
$cquot :: Word128 -> Word128 -> Word128
Integral
    , Ord Word128
(Word128, Word128) -> Int
(Word128, Word128) -> [Word128]
(Word128, Word128) -> Word128 -> Bool
(Word128, Word128) -> Word128 -> Int
forall a.
Ord a
-> ((a, a) -> [a])
-> ((a, a) -> a -> Int)
-> ((a, a) -> a -> Int)
-> ((a, a) -> a -> Bool)
-> ((a, a) -> Int)
-> ((a, a) -> Int)
-> Ix a
unsafeRangeSize :: (Word128, Word128) -> Int
$cunsafeRangeSize :: (Word128, Word128) -> Int
rangeSize :: (Word128, Word128) -> Int
$crangeSize :: (Word128, Word128) -> Int
inRange :: (Word128, Word128) -> Word128 -> Bool
$cinRange :: (Word128, Word128) -> Word128 -> Bool
unsafeIndex :: (Word128, Word128) -> Word128 -> Int
$cunsafeIndex :: (Word128, Word128) -> Word128 -> Int
index :: (Word128, Word128) -> Word128 -> Int
$cindex :: (Word128, Word128) -> Word128 -> Int
range :: (Word128, Word128) -> [Word128]
$crange :: (Word128, Word128) -> [Word128]
Ix
    , Integer -> Word128
Word128 -> Word128
Word128 -> Word128 -> Word128
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> Word128
$cfromInteger :: Integer -> Word128
signum :: Word128 -> Word128
$csignum :: Word128 -> Word128
abs :: Word128 -> Word128
$cabs :: Word128 -> Word128
negate :: Word128 -> Word128
$cnegate :: Word128 -> Word128
* :: Word128 -> Word128 -> Word128
$c* :: Word128 -> Word128 -> Word128
- :: Word128 -> Word128 -> Word128
$c- :: Word128 -> Word128 -> Word128
+ :: Word128 -> Word128 -> Word128
$c+ :: Word128 -> Word128 -> Word128
Num
    , Eq Word128
Word128 -> Word128 -> Bool
Word128 -> Word128 -> Ordering
Word128 -> Word128 -> Word128
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Word128 -> Word128 -> Word128
$cmin :: Word128 -> Word128 -> Word128
max :: Word128 -> Word128 -> Word128
$cmax :: Word128 -> Word128 -> Word128
>= :: Word128 -> Word128 -> Bool
$c>= :: Word128 -> Word128 -> Bool
> :: Word128 -> Word128 -> Bool
$c> :: Word128 -> Word128 -> Bool
<= :: Word128 -> Word128 -> Bool
$c<= :: Word128 -> Word128 -> Bool
< :: Word128 -> Word128 -> Bool
$c< :: Word128 -> Word128 -> Bool
compare :: Word128 -> Word128 -> Ordering
$ccompare :: Word128 -> Word128 -> Ordering
Ord
    , ReadPrec [Word128]
ReadPrec Word128
Int -> ReadS Word128
ReadS [Word128]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Word128]
$creadListPrec :: ReadPrec [Word128]
readPrec :: ReadPrec Word128
$creadPrec :: ReadPrec Word128
readList :: ReadS [Word128]
$creadList :: ReadS [Word128]
readsPrec :: Int -> ReadS Word128
$creadsPrec :: Int -> ReadS Word128
Read
    , Num Word128
Ord Word128
Word128 -> Rational
forall a. Num a -> Ord a -> (a -> Rational) -> Real a
toRational :: Word128 -> Rational
$ctoRational :: Word128 -> Rational
Real
    , Int -> Word128 -> ShowS
[Word128] -> ShowS
Word128 -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Word128] -> ShowS
$cshowList :: [Word128] -> ShowS
show :: Word128 -> String
$cshow :: Word128 -> String
showsPrec :: Int -> Word128 -> ShowS
$cshowsPrec :: Int -> Word128 -> ShowS
Show
    , Ptr Word128 -> IO Word128
Ptr Word128 -> Int -> IO Word128
Ptr Word128 -> Int -> Word128 -> IO ()
Ptr Word128 -> Word128 -> IO ()
Word128 -> Int
forall b. Ptr b -> Int -> IO Word128
forall b. Ptr b -> Int -> Word128 -> IO ()
forall a.
(a -> Int)
-> (a -> Int)
-> (Ptr a -> Int -> IO a)
-> (Ptr a -> Int -> a -> IO ())
-> (forall b. Ptr b -> Int -> IO a)
-> (forall b. Ptr b -> Int -> a -> IO ())
-> (Ptr a -> IO a)
-> (Ptr a -> a -> IO ())
-> Storable a
poke :: Ptr Word128 -> Word128 -> IO ()
$cpoke :: Ptr Word128 -> Word128 -> IO ()
peek :: Ptr Word128 -> IO Word128
$cpeek :: Ptr Word128 -> IO Word128
pokeByteOff :: forall b. Ptr b -> Int -> Word128 -> IO ()
$cpokeByteOff :: forall b. Ptr b -> Int -> Word128 -> IO ()
peekByteOff :: forall b. Ptr b -> Int -> IO Word128
$cpeekByteOff :: forall b. Ptr b -> Int -> IO Word128
pokeElemOff :: Ptr Word128 -> Int -> Word128 -> IO ()
$cpokeElemOff :: Ptr Word128 -> Int -> Word128 -> IO ()
peekElemOff :: Ptr Word128 -> Int -> IO Word128
$cpeekElemOff :: Ptr Word128 -> Int -> IO Word128
alignment :: Word128 -> Int
$calignment :: Word128 -> Int
sizeOf :: Word128 -> Int
$csizeOf :: Word128 -> Int
Storable
    )

-- | Construct a 'Word128'
word128 ::
     Word64 -- ^ Most significant bits
  -> Word64 -- ^ Least significant bits
  -> Word128
word128 :: Word64 -> Word64 -> Word128
word128 Word64
hi Word64
lo = Word128 -> Word128
Word128 (Word64 -> Word64 -> Word128
WW.Word128 Word64
hi Word64
lo)

-- | Get the most significant 64 bits from a 'Word128'
word128MS64 :: Word128 -> Word64
word128MS64 :: Word128 -> Word64
word128MS64 (Word128 (WW.Word128 Word64
hi Word64
_)) = Word64
hi

-- | Get the least significant 64 bits from a 'Word128'
word128LS64 :: Word128 -> Word64
word128LS64 :: Word128 -> Word64
word128LS64 (Word128 (WW.Word128 Word64
_ Word64
lo)) = Word64
lo

{-------------------------------------------------------------------------------
  Instances
-------------------------------------------------------------------------------}

instance ByteSwap Word128 where
  byteSwap :: Word128 -> Word128
byteSwap (Word128 (WW.Word128 Word64
hi Word64
lo)) =
      Word128 -> Word128
Word128 forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> Word128
WW.Word128 (Word64 -> Word64
byteSwap64 Word64
lo) (Word64 -> Word64
byteSwap64 Word64
hi)