-- | Numeric conversions from high level representations to the JVM representations.
module H2JVM.Internal.Convert.Numbers (toJVMFloat, toJVMLong, toJVMDouble) where

import Data.Binary.Get (getWord32be, runGet)
import Data.Binary.Put (putDoublebe, putFloatbe, runPut)
import Data.Bits (Bits (..))
import Data.Int (Int64)
import Witch (unsafeInto)

import H2JVM.Internal.Raw.Types (U4)

-- | Converts a Haskell float to the JVM representation.
toJVMFloat :: Float -> U4
toJVMFloat :: Float -> U4
toJVMFloat Float
f = Get U4 -> ByteString -> U4
forall a. Get a -> ByteString -> a
runGet Get U4
getWord32be (Put -> ByteString
runPut (Put -> ByteString) -> Put -> ByteString
forall a b. (a -> b) -> a -> b
$ Float -> Put
putFloatbe Float
f) -- This is probably very inefficient

-- | Converts a Haskell long to the JVM representation (two 'U4's), splitting the long into its high and low bits.
toJVMLong :: Int64 -> (U4, U4)
toJVMLong :: Int64 -> (U4, U4)
toJVMLong Int64
l = (Int64 -> U4
forall target source.
(HasCallStack, TryFrom source target, Show source, Typeable source,
 Typeable target) =>
source -> target
unsafeInto (Int64
l Int64 -> Int -> Int64
forall a. Bits a => a -> Int -> a
`shiftR` Int
32), Int64 -> U4
forall target source.
(HasCallStack, TryFrom source target, Show source, Typeable source,
 Typeable target) =>
source -> target
unsafeInto Int64
l)

-- | Converts a Haskell Double to the JVM representation (two 'U4's), splitting the value into its high and low bits.
toJVMDouble :: Double -> (U4, U4)
toJVMDouble :: Double -> (U4, U4)
toJVMDouble Double
d = do
    let bs :: ByteString
bs = Put -> ByteString
runPut (Double -> Put
putDoublebe Double
d)
    (Get (U4, U4) -> ByteString -> (U4, U4))
-> ByteString -> Get (U4, U4) -> (U4, U4)
forall a b c. (a -> b -> c) -> b -> a -> c
flip Get (U4, U4) -> ByteString -> (U4, U4)
forall a. Get a -> ByteString -> a
runGet ByteString
bs (Get (U4, U4) -> (U4, U4)) -> Get (U4, U4) -> (U4, U4)
forall a b. (a -> b) -> a -> b
$ do
        high <- Get U4
getWord32be
        low <- getWord32be
        pure (high, low)