diff options
author | Roman Smrž <roman.smrz@seznam.cz> | 2025-03-31 20:27:34 +0200 |
---|---|---|
committer | Roman Smrž <roman.smrz@seznam.cz> | 2025-04-05 20:04:52 +0200 |
commit | ec42d7bb3ba7374b3d0afcd6e2c9e9b616679105 (patch) | |
tree | 2d27a21ae2a104d0d9e34ab6ea574f28d41591d2 /src/Erebos/UUID.hs | |
parent | 7a8e3fa16970296de6e553631fab7cfd67f461c2 (diff) |
Replace uuid package with custom module
Avoids transitive denpednecies not buildable with wasm backend.
Diffstat (limited to 'src/Erebos/UUID.hs')
-rw-r--r-- | src/Erebos/UUID.hs | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/Erebos/UUID.hs b/src/Erebos/UUID.hs new file mode 100644 index 0000000..353cc0e --- /dev/null +++ b/src/Erebos/UUID.hs @@ -0,0 +1,78 @@ +module Erebos.UUID ( + UUID, + toString, fromString, + toText, fromText, + toASCIIBytes, fromASCIIBytes, + nextRandom, +) where + +import Control.Monad + +import Crypto.Random.Entropy + +import Data.Bits +import Data.ByteString (ByteString) +import Data.ByteString qualified as BS +import Data.ByteString.Char8 qualified as BSC +import Data.Text (Text) +import Data.Text.Encoding + +import Erebos.Util + + +newtype UUID = UUID ByteString + deriving (Eq, Ord) + +instance Show UUID where + show = toString + + +toString :: UUID -> String +toString = BSC.unpack . toASCIIBytes + +fromString :: String -> Maybe UUID +fromString = fromASCIIBytes . BSC.pack + +toText :: UUID -> Text +toText = decodeUtf8 . toASCIIBytes + +fromText :: Text -> Maybe UUID +fromText = fromASCIIBytes . encodeUtf8 + +toASCIIBytes :: UUID -> ByteString +toASCIIBytes (UUID uuid) = BS.concat + [ showHex $ BS.take 4 $ uuid + , BSC.singleton '-' + , showHex $ BS.take 2 $ BS.drop 4 uuid + , BSC.singleton '-' + , showHex $ BS.take 2 $ BS.drop 6 uuid + , BSC.singleton '-' + , showHex $ BS.take 2 $ BS.drop 8 uuid + , BSC.singleton '-' + , showHex $ BS.drop 10 uuid + ] + +fromASCIIBytes :: ByteString -> Maybe UUID +fromASCIIBytes bs = do + guard $ BS.length bs == 36 + guard $ BSC.index bs 8 == '-' + guard $ BSC.index bs 13 == '-' + guard $ BSC.index bs 18 == '-' + guard $ BSC.index bs 23 == '-' + UUID . BS.concat <$> sequence + [ readHex $ BS.take 8 $ bs + , readHex $ BS.take 4 $ BS.drop 9 bs + , readHex $ BS.take 4 $ BS.drop 14 bs + , readHex $ BS.take 4 $ BS.drop 19 bs + , readHex $ BS.drop 24 bs + ] + + +nextRandom :: IO UUID +nextRandom = do + [ b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf ] + <- BS.unpack <$> getEntropy 16 + let version = 4 + b6' = b6 .&. 0x0f .|. (version `shiftL` 4) + b8' = b8 .&. 0x3f .|. 0x80 + return $ UUID $ BS.pack [ b0, b1, b2, b3, b4, b5, b6', b7, b8', b9, ba, bb, bc, bd, be, bf ] |