{-| Description: A small helper to generate GUIDs A small helper to generate GUIDs. Provides functions to generate simple GUIDs. -} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE DeriveGeneric #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Web.DDP.Deadpan.GUID ( GUID() -- No export of constructors in order to protect generation of IDs , newGuid , hashTriple , newGuidInt , newGuidString , newGuidText , makeEJsonId , ejson2guid , guid2SubReady , guid2NoSub ) where -- Internal Imports import Data.EJson -- External Imports import System.Random import System.CPUTime import Data.Time import Data.Text import Text.Printf import Data.Hashable import GHC.Generics instance Hashable DiffTime where hashWithSalt s = (hashWithSalt s :: Double -> Int) . realToFrac deriving instance Generic Day instance Hashable Day deriving instance Generic UTCTime instance Hashable UTCTime newtype GUID = GUID {getGuidText :: Text} deriving (Eq,Ord,Generic,Hashable) instance Show GUID where show = show . getGuidText hashTriple :: IO (Integer,UTCTime,Integer) hashTriple = do cpu <- getCPUTime time <- getCurrentTime rand <- randomIO return (cpu,time,rand) newGuidInt :: IO Int newGuidInt = hash `fmap` hashTriple newGuidString :: IO String newGuidString = printf "%016x" `fmap` newGuidInt newGuidText :: IO Text newGuidText = pack `fmap` newGuidString newGuid :: IO GUID newGuid = GUID `fmap` newGuidText makeEJsonId :: GUID -> EJsonValue makeEJsonId key = ejobject [("id", ejstring (getGuidText key))] ejson2guid :: EJsonValue -> Maybe GUID ejson2guid v = fmap GUID $ v ^? _EJObjectKeyString "id" -- | Construct a matcher for subscription-ready based on ID. -- -- TODO: Allow for propper matcher behavior and abstraction a-la clojure's midje methods. -- This is important as there could be multiple subscription ids listed here... -- guid2SubReady :: GUID -> EJsonValue guid2SubReady key = ejobject [("msg","ready"), ("subs", ejarray [ejstring (getGuidText key)])] -- | Construct a matcher for subscription failure based on ID. -- guid2NoSub :: GUID -> EJsonValue guid2NoSub key = ejobject [("msg","nosub"), ("id", ejstring (getGuidText key))]