typed-uuid-0.2.0.0: src/Data/UUID/Typed.hs
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
module Data.UUID.Typed
( UUID (..),
uuidText,
uuidString,
uuidASCIIBytes,
uuidLazyASCIIBytes,
nextRandomUUID,
parseUUIDText,
parseUUIDString,
parseUUIDAsciiBytes,
parseUUIDLazyAsciiBytes,
jsonParseUUID,
textJSONParseUUID,
)
where
import Autodocodec
import Control.DeepSeq
import Control.Monad.IO.Class
import Data.Aeson as JSON
import Data.Aeson.Types as JSON
import Data.Binary
import qualified Data.ByteString as SB
import qualified Data.ByteString.Lazy as LB
import Data.Data
import Data.Hashable
import Data.Text (Text)
import qualified Data.UUID as UUID
import qualified Data.UUID.V4 as UUID
import Data.Validity
import Data.Validity.UUID ()
import Foreign.Storable
import GHC.Generics
import System.Random
import Web.HttpApiData
newtype UUID a
= UUID
{ unUUID :: UUID.UUID
}
deriving stock (Eq, Ord, Generic, Show, Read, Data)
deriving newtype (Storable, Binary, NFData, Hashable, Random, Validity)
deriving (FromJSON, ToJSON) via (Autodocodec (UUID a))
-- | See 'UUID.toText'
uuidText :: UUID a -> Text
uuidText (UUID uuid) = UUID.toText uuid
-- | See 'UUID.toString'
uuidString :: UUID a -> String
uuidString (UUID uuid) = UUID.toString uuid
-- | See 'UUID.toASCIIBytes'
uuidASCIIBytes :: UUID a -> SB.ByteString
uuidASCIIBytes (UUID uuid) = UUID.toASCIIBytes uuid
-- | See 'UUID.toLazyASCIIBytes'
uuidLazyASCIIBytes :: UUID a -> LB.ByteString
uuidLazyASCIIBytes (UUID uuid) = UUID.toLazyASCIIBytes uuid
-- | See 'UUID.nextRandom'
nextRandomUUID :: MonadIO m => m (UUID a)
nextRandomUUID = liftIO $ UUID <$> UUID.nextRandom
-- | See 'UUID.fromText'
parseUUIDText :: Text -> Maybe (UUID a)
parseUUIDText = fmap UUID . UUID.fromText
-- | See 'UUID.fromString'
parseUUIDString :: String -> Maybe (UUID a)
parseUUIDString = fmap UUID . UUID.fromString
-- | See 'UUID.parseUUIDAsciiBytes'
parseUUIDAsciiBytes :: SB.ByteString -> Maybe (UUID a)
parseUUIDAsciiBytes = fmap UUID . UUID.fromASCIIBytes
-- | See 'UUID.parseUUIDLazyAsciiBytes'
parseUUIDLazyAsciiBytes :: LB.ByteString -> Maybe (UUID a)
parseUUIDLazyAsciiBytes = fmap UUID . UUID.fromLazyASCIIBytes
instance FromJSONKey (UUID a) where
fromJSONKey = FromJSONKeyTextParser textJSONParseUUID
instance ToJSONKey (UUID a) where
toJSONKey = toJSONKeyText (UUID.toText . unUUID)
jsonParseUUID :: Value -> Parser (UUID a)
jsonParseUUID = withText "UUID" textJSONParseUUID
instance HasCodec (UUID a) where
codec = bimapCodec f uuidText codec
where
f t =
case UUID.fromText t of
Nothing -> Left "Invalid Text when parsing UUID"
Just u -> Right $ UUID u
textJSONParseUUID :: Text -> Parser (UUID a)
textJSONParseUUID t =
case UUID.fromText t of
Nothing -> fail "Invalid Text when parsing UUID"
Just u -> pure $ UUID u
instance FromHttpApiData (UUID a) where
parseUrlPiece t =
case UUID.fromText t of
Nothing -> Left $ "Invalid UUID in Url Piece: " <> t
Just uuid -> pure $ UUID uuid
instance ToHttpApiData (UUID a) where
toUrlPiece (UUID uuid) = UUID.toText uuid