-- | Description : UUID generator and data structure
--
-- Generate, parse, and pretty print UUIDs for use with IPython.
module IHaskell.IPython.Message.UUID (UUID, random, randoms, uuidToString) where

import           Control.Monad (mzero, replicateM)
import           Data.Aeson
import           Data.Text (pack)
import           Data.UUID.V4 (nextRandom)

-- | A UUID (universally unique identifier).
data UUID =
     -- We use an internal string representation because for the purposes of IPython, it
     -- matters whether the letters are uppercase or lowercase and whether the dashes are
     -- present in the correct locations. For the purposes of new UUIDs, it does not matter,
     -- but IPython expects UUIDs passed to kernels to be returned unchanged, so we cannot
     -- actually parse them.
      UUID { UUID -> String
uuidToString :: String }
  deriving (Int -> UUID -> ShowS
[UUID] -> ShowS
UUID -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [UUID] -> ShowS
$cshowList :: [UUID] -> ShowS
show :: UUID -> String
$cshow :: UUID -> String
showsPrec :: Int -> UUID -> ShowS
$cshowsPrec :: Int -> UUID -> ShowS
Show, ReadPrec [UUID]
ReadPrec UUID
Int -> ReadS UUID
ReadS [UUID]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [UUID]
$creadListPrec :: ReadPrec [UUID]
readPrec :: ReadPrec UUID
$creadPrec :: ReadPrec UUID
readList :: ReadS [UUID]
$creadList :: ReadS [UUID]
readsPrec :: Int -> ReadS UUID
$creadsPrec :: Int -> ReadS UUID
Read, UUID -> UUID -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: UUID -> UUID -> Bool
$c/= :: UUID -> UUID -> Bool
== :: UUID -> UUID -> Bool
$c== :: UUID -> UUID -> Bool
Eq, Eq UUID
UUID -> UUID -> Bool
UUID -> UUID -> Ordering
UUID -> UUID -> UUID
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 :: UUID -> UUID -> UUID
$cmin :: UUID -> UUID -> UUID
max :: UUID -> UUID -> UUID
$cmax :: UUID -> UUID -> UUID
>= :: UUID -> UUID -> Bool
$c>= :: UUID -> UUID -> Bool
> :: UUID -> UUID -> Bool
$c> :: UUID -> UUID -> Bool
<= :: UUID -> UUID -> Bool
$c<= :: UUID -> UUID -> Bool
< :: UUID -> UUID -> Bool
$c< :: UUID -> UUID -> Bool
compare :: UUID -> UUID -> Ordering
$ccompare :: UUID -> UUID -> Ordering
Ord)

-- | Generate a list of random UUIDs.
randoms :: Int      -- ^ Number of UUIDs to generate.
        -> IO [UUID]
randoms :: Int -> IO [UUID]
randoms Int
n = forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
n IO UUID
random

-- | Generate a single random UUID.
random :: IO UUID
random :: IO UUID
random = String -> UUID
UUID forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Show a => a -> String
show forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO UUID
nextRandom

-- Allows reading and writing UUIDs as Strings in JSON.
instance FromJSON UUID where
  parseJSON :: Value -> Parser UUID
parseJSON val :: Value
val@(String Text
_) = String -> UUID
UUID forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON Value
val

  -- UUIDs must be Strings.
  parseJSON Value
_ = forall (m :: * -> *) a. MonadPlus m => m a
mzero

instance ToJSON UUID where
  -- Extract the string from the UUID.
  toJSON :: UUID -> Value
toJSON (UUID String
str) = Text -> Value
String forall a b. (a -> b) -> a -> b
$ String -> Text
pack String
str