{-|
Module:      Z.Data.Parser.UUID
Description : Parsers for UUID.
Copyright:   (c) 2020 Dong Han
License:     BSD3
Maintainer:  Dong <winterland1989@gmail.com>
Stability:   experimental
Portability: portable

Parsers for parsing UUID.
-}

module Z.Data.Parser.UUID
    ( uuid
    , decodeUUID
    ) where

import           Z.Data.ASCII
import qualified Z.Data.Parser.Base         as P
import qualified Z.Data.Parser.Numeric      as P
import           Data.UUID.Types.Internal

-- | Parse texutal UUID bytes(lower or upper-cased), e.g. @550e8400-e29b-41d4-a716-446655440000@
uuid :: P.Parser UUID
{-# INLINABLE uuid #-}
uuid :: Parser UUID
uuid =  do
    Bytes
p1 <- (Word8 -> Bool) -> Int -> Parser Bytes
P.takeN Word8 -> Bool
isHexDigit Int
8
    Word8 -> Parser ()
P.word8 Word8
HYPHEN
    Bytes
p2 <- (Word8 -> Bool) -> Int -> Parser Bytes
P.takeN Word8 -> Bool
isHexDigit Int
4
    Word8 -> Parser ()
P.word8 Word8
HYPHEN
    Bytes
p3 <- (Word8 -> Bool) -> Int -> Parser Bytes
P.takeN Word8 -> Bool
isHexDigit Int
4
    Word8 -> Parser ()
P.word8 Word8
HYPHEN
    Bytes
p4 <- (Word8 -> Bool) -> Int -> Parser Bytes
P.takeN Word8 -> Bool
isHexDigit Int
4
    Word8 -> Parser ()
P.word8 Word8
HYPHEN
    Bytes
p5 <- (Word8 -> Bool) -> Int -> Parser Bytes
P.takeN Word8 -> Bool
isHexDigit Int
12

    let !w1 :: Word64
w1 = forall a. (Integral a, Bits a) => a -> Bytes -> a
P.hexLoop (forall a. (Integral a, Bits a) => a -> Bytes -> a
P.hexLoop (forall a. (Integral a, Bits a) => a -> Bytes -> a
P.hexLoop Word64
0 Bytes
p1) Bytes
p2) Bytes
p3
        !w2 :: Word64
w2 = forall a. (Integral a, Bits a) => a -> Bytes -> a
P.hexLoop (forall a. (Integral a, Bits a) => a -> Bytes -> a
P.hexLoop Word64
0 Bytes
p4) Bytes
p5

    forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word64 -> Word64 -> UUID
UUID Word64
w1 Word64
w2)

-- | Decode binary UUID(two 64-bits word in big-endian), as described in <https://datatracker.ietf.org/doc/html/rfc4122 RFC 4122>. 
decodeUUID :: P.Parser UUID
{-# INLINABLE  decodeUUID #-}
decodeUUID :: Parser UUID
decodeUUID = Word64 -> Word64 -> UUID
UUID forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Word64
P.decodeWord64BE forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word64
P.decodeWord64BE