asif-6.0.0: src/Arbor/File/Format/Asif/Get.hs
module Arbor.File.Format.Asif.Get where
import Arbor.File.Format.Asif.ByteString.Builder
import Arbor.File.Format.Asif.Data.Ip (word32ToIpv4, word32x4ToIpv6)
import Control.Lens
import Control.Monad
import Data.Binary.Get
import Data.Monoid ((<>))
import Data.Text (Text)
import Data.Thyme.Clock (microseconds)
import Data.Thyme.Clock.POSIX (POSIXTime)
import Data.Thyme.Time.Core (UTCTime, posixSecondsToUTCTime)
import Data.Word (Word32)
import HaskellWorks.Data.Network.Ip.Validity (Canonical)
import qualified Data.Attoparsec.ByteString as AP
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Lazy.Char8 as LC8
import qualified Data.Text.Encoding as T
import qualified HaskellWorks.Data.Network.Ip.Ipv4 as IP4
import qualified HaskellWorks.Data.Network.Ip.Ipv6 as IP6
getMagic :: AP.Parser BS.ByteString -> Get ()
getMagic magicParser = do
a <- getLazyByteString magicLength
case AP.parseOnly magicParser (LBS.toStrict a) of
Right _ -> return ()
Left errorMessage -> fail $ "wrong magic: \"" <> LC8.unpack a <> "\", expected: " <> errorMessage
getSegmentLength :: Get Int
getSegmentLength = fromIntegral <$> getInt64le
getSegmentPosition :: Get (Int, Int)
getSegmentPosition = (,)
<$> (fromIntegral <$> getInt32le)
<*> (fromIntegral <$> getInt32le)
getSegmentPositions :: Get [(Int, Int)]
getSegmentPositions = do
n <- getSegmentLength
replicateM n getSegmentPosition
getHeader :: AP.Parser BS.ByteString -> Get [(Int, Int)]
getHeader magicParser = do
getMagic magicParser
getSegmentPositions
getTimeMicro64 :: Get POSIXTime
getTimeMicro64 = (^. from microseconds) <$> getInt64le
getTimeMillis :: Get UTCTime
getTimeMillis =
let toTime ms = (ms * 1000) ^. from microseconds & posixSecondsToUTCTime
in getInt64le <&> toTime
getTimeMicros :: Get UTCTime
getTimeMicros =
let toTime ms = ms ^. from microseconds & posixSecondsToUTCTime
in getInt64le <&> toTime
getWord32x4 :: Get (Word32, Word32, Word32, Word32)
getWord32x4 = do
a <- getWord32be
b <- getWord32be
c <- getWord32be
d <- getWord32be
return (a, b, c, d)
getBool :: Get Bool
getBool = getWord8 <&> (/= 0)
getIpv4 :: Get IP4.IpAddress
getIpv4 = getWord32le <&> word32ToIpv4
getIpv6 :: Get IP6.IpAddress
getIpv6 = getWord32x4 <&> word32x4ToIpv6
getIpv4Block :: Get (IP4.IpBlock Canonical)
getIpv4Block =
let toIpBlock w32 w8 = IP4.IpBlock (IP4.IpAddress w32) (IP4.IpNetMask w8)
in toIpBlock <$> getWord32le <*> getWord8
getIpv6Block :: Get (IP6.IpBlock Canonical)
getIpv6Block =
let toIpBlock w128 w8 = IP6.IpBlock (IP6.IpAddress w128) (IP6.IpNetMask w8)
in toIpBlock <$> getWord32x4 <*> getWord8
getTextUtf8Z :: Get Text
getTextUtf8Z = T.decodeUtf8 . LBS.toStrict <$> getLazyByteStringNul
getNullTerminatedString :: Get LBS.ByteString
getNullTerminatedString = getLazyByteStringNul