mmzk-typeid 0.6.0.0 → 0.6.0.1
raw patch · 9 files changed
+97/−52 lines, 9 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +9/−1
- README.md +3/−2
- mmzk-typeid.cabal +4/−4
- src/Data/KindID/V1.hs +8/−7
- src/Data/KindID/V4.hs +8/−7
- src/Data/KindID/V5.hs +8/−7
- src/Data/KindID/V7.hs +8/−7
- src/Data/TypeID/Internal.hs +5/−5
- test/Spec.hs +44/−12
CHANGELOG.md view
@@ -1,7 +1,15 @@ # Revision history for mmzk-typeid -## 0.6.0.0 -- Unreleased+## 0.6.0.1 -- 2024-04-26++* Fix typo in the maintainer's email address.+ * Astounded at the fact that I mismatched the local part and domain name and didn't realise it for a year.+* More test cases on parsing.+* Fix other typos and inconsistencies in the documentation.+++## 0.6.0.0 -- 2024-04-19 * Update implementation to conform with specification v0.3.0. * Allow `TypeID` prefix to contain underscores.
README.md view
@@ -21,7 +21,7 @@ In addition to the features provided by [TypeID](https://github.com/jetpack-io/typeid), this implementation also supports: 1. Generating TypeIDs in a batch. They are guaranteed to have the same timestamp (up to the first 32768 ids) and of ascending order;-2. Encoding the prefix in the [type level](https://hackage.haskell.org/package/mmzk-typeid/docs/Data-KindID.html), so that if you accidentally pass in a wrong prefix, the code won't compile, avoiding the need for runtime checks.+2. Encoding the prefix in the [type level](https://hackage.haskell.org/package/mmzk-typeid/docs/Data-KindID.html), so that if you accidentally pass in a wrong prefix, the code won't compile, avoiding the need for runtime checks; 3. Support TypeID with other UUID versions. Currently v7 (default), v1, v4, and v5 are supported. ## Quick start@@ -190,6 +190,7 @@ ```Haskell {-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeApplications #-} import Data.KindID@@ -207,7 +208,7 @@ type PrefixSymbol 'Comment = "comment" ``` -Now we can use `Prefix` as a prefix for `KindID`s, e.g.+Now we can use `Prefix` as a prefix for `KindID`s, *e.g.* ```Haskell main :: IO ()
mmzk-typeid.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: mmzk-typeid-version: 0.6.0.0+version: 0.6.0.1 synopsis: A TypeID implementation for Haskell description:@@ -31,12 +31,12 @@ homepage: https://github.com/MMZK1526/mmzk-typeid bug-reports: https://github.com/MMZK1526/mmzk-typeid/issues license: MIT-author: Yitang Chen <mmzk1526@ic.ac.uk>-maintainer: Yitang Chen <mmzk1526@ic.ac.uk>+author: Yitang Chen <mmzk1526@outlook.com>+maintainer: Yitang Chen <mmzk1526@outlook.com> category: Data, UUID, TypeID tested-with: GHC == 9.2.8- GHC == 9.6.2+ GHC == 9.6.1 extra-source-files: CHANGELOG.md LICENSE
src/Data/KindID/V1.hs view
@@ -105,8 +105,8 @@ toByteString = KID.toByteString {-# INLINE toByteString #-} --- | Parse a 'KindIDV1' from its 'String' representation. It is 'parseString'--- with concrete type.+-- | Parse a 'KindIDV1' from its 'String' representation. It is 'string2ID' with+-- concrete type. parseString :: forall prefix . (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix)) => String -> Either TypeIDError (KindIDV1 prefix)@@ -114,7 +114,7 @@ {-# INLINE parseString #-} -- | Parse a 'KindIDV1' from its string representation as a strict 'Text'. It is--- 'parseText' with concrete type.+-- 'text2ID' with concrete type. parseText :: forall prefix . (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix)) => Text -> Either TypeIDError (KindIDV1 prefix)@@ -122,7 +122,7 @@ {-# INLINE parseText #-} -- | Parse a 'KindIDV1' from its string representation as a lazy 'ByteString'.--- It is 'parseByteString' with concrete type.+-- It is 'byteString2ID' with concrete type. parseByteString :: forall prefix . (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix)) => ByteString -> Either TypeIDError (KindIDV1 prefix)@@ -137,7 +137,7 @@ -- | Parse a 'KindIDV1' from its string representation as a strict 'Text', -- throwing an error when the parsing fails. It is 'text2IDM' with concrete--- type. It is 'parseTextM' with concrete type.+-- type. parseTextM :: (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix), MonadIO m) => Text -> m (KindIDV1 prefix) parseTextM = KID.parseTextM@@ -145,7 +145,7 @@ -- | Parse a 'KindIDV1' from its string representation as a lazy 'ByteString', -- throwing an error when the parsing fails. It is 'byteString2IDM' with--- concrete type. It is 'parseByteStringM' with concrete type.+-- concrete type. parseByteStringM :: ( ToPrefix prefix , ValidPrefix (PrefixSymbol prefix) , MonadIO m )@@ -159,7 +159,8 @@ toTypeID = KID.toTypeID {-# INLINE toTypeID #-} --- | Convert a 'TypeIDV1' to a 'KindIDV1'.+-- | Convert a 'TypeIDV1' to a 'KindIDV1'. Returns 'Nothing' if the prefix does+-- not match. fromTypeID :: (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix)) => TypeIDV1 -> Maybe (KindIDV1 prefix) fromTypeID = KID.fromTypeID
src/Data/KindID/V4.hs view
@@ -113,8 +113,8 @@ toByteString = KID.toByteString {-# INLINE toByteString #-} --- | Parse a 'KindIDV4' from its 'String' representation. It is 'parseString'--- with concrete type.+-- | Parse a 'KindIDV4' from its 'String' representation. It is 'string2ID' with+-- concrete type. parseString :: forall prefix . (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix)) => String -> Either TypeIDError (KindIDV4 prefix)@@ -122,7 +122,7 @@ {-# INLINE parseString #-} -- | Parse a 'KindIDV4' from its string representation as a strict 'Text'. It is--- 'parseText' with concrete type.+-- 'text2ID' with concrete type. parseText :: forall prefix . (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix)) => Text -> Either TypeIDError (KindIDV4 prefix)@@ -130,7 +130,7 @@ {-# INLINE parseText #-} -- | Parse a 'KindIDV4' from its string representation as a lazy 'ByteString'.--- It is 'parseByteString' with concrete type.+-- It is 'byteString2ID' with concrete type. parseByteString :: forall prefix . (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix)) => ByteString -> Either TypeIDError (KindIDV4 prefix)@@ -145,7 +145,7 @@ -- | Parse a 'KindIDV4' from its string representation as a strict 'Text', -- throwing an error when the parsing fails. It is 'text2IDM' with concrete--- type. It is 'parseTextM' with concrete type.+-- type. parseTextM :: (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix), MonadIO m) => Text -> m (KindIDV4 prefix) parseTextM = KID.parseTextM@@ -153,7 +153,7 @@ -- | Parse a 'KindIDV4' from its string representation as a lazy 'ByteString', -- throwing an error when the parsing fails. It is 'byteString2IDM' with--- concrete type. It is 'parseByteStringM' with concrete type.+-- concrete type. parseByteStringM :: ( ToPrefix prefix , ValidPrefix (PrefixSymbol prefix) , MonadIO m )@@ -167,7 +167,8 @@ toTypeID = KID.toTypeID {-# INLINE toTypeID #-} --- | Convert a 'TypeIDV4' to a 'KindIDV4'.+-- | Convert a 'TypeIDV4' to a 'KindIDV4'. Returns 'Nothing' if the prefix does+-- not match. fromTypeID :: (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix)) => TypeIDV4 -> Maybe (KindIDV4 prefix) fromTypeID = KID.fromTypeID
src/Data/KindID/V5.hs view
@@ -106,8 +106,8 @@ toByteString = KID.toByteString {-# INLINE toByteString #-} --- | Parse a 'KindIDV5' from its 'String' representation. It is 'parseString'--- with concrete type.+-- | Parse a 'KindIDV5' from its 'String' representation. It is 'string2ID' with+-- concrete type. parseString :: forall prefix . (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix)) => String -> Either TypeIDError (KindIDV5 prefix)@@ -115,7 +115,7 @@ {-# INLINE parseString #-} -- | Parse a 'KindIDV5' from its string representation as a strict 'Text'. It is--- 'parseText' with concrete type.+-- 'text2ID' with concrete type. parseText :: forall prefix . (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix)) => Text -> Either TypeIDError (KindIDV5 prefix)@@ -123,7 +123,7 @@ {-# INLINE parseText #-} -- | Parse a 'KindIDV5' from its string representation as a lazy 'ByteString'.--- It is 'parseByteString' with concrete type.+-- It is 'byteString2ID' with concrete type. parseByteString :: forall prefix . (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix)) => ByteString -> Either TypeIDError (KindIDV5 prefix)@@ -138,7 +138,7 @@ -- | Parse a 'KindIDV5' from its string representation as a strict 'Text', -- throwing an error when the parsing fails. It is 'text2IDM' with concrete--- type. It is 'parseTextM' with concrete type.+-- type. parseTextM :: (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix), MonadIO m) => Text -> m (KindIDV5 prefix) parseTextM = KID.parseTextM@@ -146,7 +146,7 @@ -- | Parse a 'KindIDV5' from its string representation as a lazy 'ByteString', -- throwing an error when the parsing fails. It is 'byteString2IDM' with--- concrete type. It is 'parseByteStringM' with concrete type.+-- concrete type. parseByteStringM :: ( ToPrefix prefix , ValidPrefix (PrefixSymbol prefix) , MonadIO m )@@ -160,7 +160,8 @@ toTypeID = KID.toTypeID {-# INLINE toTypeID #-} --- | Convert a 'TypeIDV5' to a 'KindIDV5'.+-- | Convert a 'TypeIDV5' to a 'KindIDV5'. Returns 'Nothing' if the prefix does+-- not match. fromTypeID :: (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix)) => TypeIDV5 -> Maybe (KindIDV5 prefix) fromTypeID = KID.fromTypeID
src/Data/KindID/V7.hs view
@@ -147,8 +147,8 @@ toByteString = KID.toByteString {-# INLINE toByteString #-} --- | Parse a 'KindID' from its 'String' representation. It is 'parseString'--- with concrete type.+-- | Parse a 'KindID' from its 'String' representation. It is 'string2ID' with+-- concrete type. parseString :: forall prefix . (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix)) => String -> Either TypeIDError (KindID prefix)@@ -156,7 +156,7 @@ {-# INLINE parseString #-} -- | Parse a 'KindID' from its string representation as a strict 'Text'. It is--- 'parseText' with concrete type.+-- 'text2ID' with concrete type. parseText :: forall prefix . (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix)) => Text -> Either TypeIDError (KindID prefix)@@ -164,7 +164,7 @@ {-# INLINE parseText #-} -- | Parse a 'KindID' from its string representation as a lazy 'ByteString'. It--- is 'parseByteString' with concrete type.+-- is 'byteString2ID' with concrete type. parseByteString :: forall prefix . (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix)) => ByteString -> Either TypeIDError (KindID prefix)@@ -179,7 +179,7 @@ -- | Parse a 'KindID' from its string representation as a strict 'Text', -- throwing an error when the parsing fails. It is 'text2IDM' with concrete--- type. It is 'parseTextM' with concrete type.+-- type. parseTextM :: (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix), MonadIO m) => Text -> m (KindID prefix) parseTextM = KID.parseTextM@@ -187,7 +187,7 @@ -- | Parse a 'KindID' from its string representation as a lazy 'ByteString', -- throwing an error when the parsing fails. It is 'byteString2IDM' with--- concrete type. It is 'parseByteStringM' with concrete type.+-- concrete type. parseByteStringM :: ( ToPrefix prefix , ValidPrefix (PrefixSymbol prefix) , MonadIO m )@@ -201,7 +201,8 @@ toTypeID = KID.toTypeID {-# INLINE toTypeID #-} --- | Convert a 'TypeID' to a 'KindID'.+-- | Convert a 'TypeID' to a 'KindID'. Returns 'Nothing' if the prefix does not+-- match. fromTypeID :: (ToPrefix prefix, ValidPrefix (PrefixSymbol prefix)) => TypeID -> Maybe (KindID prefix) fromTypeID = KID.fromTypeID
src/Data/TypeID/Internal.hs view
@@ -31,6 +31,7 @@ import Data.Text (Text) import qualified Data.Text as T import Data.Text.Encoding+import Data.Tuple import Data.Typeable (Typeable) import Data.TypeID.Class import Data.TypeID.Error@@ -40,9 +41,8 @@ import qualified Data.UUID.V5 as V5 import qualified Data.UUID.V7 as V7 import Data.UUID.Versions-import System.Random import Foreign-import Data.Tuple+import System.Random -- | This data type also supports 'Data.TypeID.V7.TypeID's with 'UUID' versions -- other than v7.@@ -621,13 +621,13 @@ -- | Generate a new 'Data.TypeID.V7.TypeID' from a prefix based on stateless -- 'UUID'v7, but without checking if the prefix is valid.-unsafeGenTypeID' :: MonadIO m => Text -> m (TypeID' V7)+unsafeGenTypeID' :: MonadIO m => Text -> m (TypeID' 'V7) unsafeGenTypeID' prefix = TypeID' prefix <$> V7.genUUID' {-# INLINE unsafeGenTypeID' #-} -- | Generate a new 'TypeID'' ''V4' from a prefix based on insecure 'UUID'v4, -- but without checking if the prefix is valid.-unsafeGenTypeIDV4' :: MonadIO m => Text -> m (TypeID' V4)+unsafeGenTypeIDV4' :: MonadIO m => Text -> m (TypeID' 'V4) unsafeGenTypeIDV4' prefix = TypeID' prefix <$> liftIO randomIO {-# INLINE unsafeGenTypeIDV4' #-} @@ -640,7 +640,7 @@ -- -- It is guaranteed that the first 32768 'Data.TypeID.V7.TypeID's are generated -- at the same timestamp.-unsafeGenTypeIDs :: MonadIO m => Text -> Word16 -> m [TypeID' V7]+unsafeGenTypeIDs :: MonadIO m => Text -> Word16 -> m [TypeID' 'V7] unsafeGenTypeIDs prefix n = map (TypeID' prefix) <$> V7.genUUIDs n {-# INLINE unsafeGenTypeIDs #-}
test/Spec.hs view
@@ -117,6 +117,14 @@ case string2ID @TypeID "mmzk_00041061050r3gg28a1c60t3gf" of Left err -> expectationFailure $ "Parse error: " ++ show err Right tid -> getPrefix tid `shouldBe` "mmzk"+ it "can parse TypeID from Text" do+ case text2ID @TypeID "mmzk_00041061050r3gg28a1c60t3gf" of+ Left err -> expectationFailure $ "Parse error: " ++ show err+ Right tid -> getPrefix tid `shouldBe` "mmzk"+ it "can parse TypeID from ByteString" do+ case byteString2ID @TypeID "mmzk_00041061050r3gg28a1c60t3gf" of+ Left err -> expectationFailure $ "Parse error: " ++ show err+ Right tid -> getPrefix tid `shouldBe` "mmzk" describe "Parse TypeID" do let invalidPrefixes = [ ("caps", "PREFIX")@@ -161,9 +169,9 @@ tid <- genID @TypeID "mmzk" tid' <- genID @TypeID "foo" let mapping = M.fromList [(tid, tid')]- let json = encode mapping- decode json `shouldBe` Just mapping- fmap encode (decode @(Map TypeID TypeID) json) `shouldBe` Just json+ let tJson = encode mapping+ decode tJson `shouldBe` Just mapping+ fmap encode (decode @(Map TypeID TypeID) tJson) `shouldBe` Just tJson describe "Valid JSON value" do forM_ valid \(TestData n tid (Just pref) (Just uid)) -> it n do case decode @TypeID (fromString $ show tid) of@@ -321,6 +329,14 @@ case string2ID @TypeIDV1 "mmzk_5hjpeh96458fct8t49fnf9farw" of Left err -> expectationFailure $ "Parse error: " ++ show err Right tid -> getPrefix tid `shouldBe` "mmzk"+ it "can parse TypeIDV1 from Text" do+ case text2ID @TypeID "mmzk_00041061050r3gg28a1c60t3gf" of+ Left err -> expectationFailure $ "Parse error: " ++ show err+ Right tid -> getPrefix tid `shouldBe` "mmzk"+ it "can parse TypeIDV1 from ByteString" do+ case byteString2ID @TypeID "mmzk_00041061050r3gg28a1c60t3gf" of+ Left err -> expectationFailure $ "Parse error: " ++ show err+ Right tid -> getPrefix tid `shouldBe` "mmzk" describe "Parse TypeIDV1" do let invalidPrefixes = [ ("caps", "PREFIX")@@ -365,9 +381,9 @@ tid <- genID @TypeIDV1 "mmzk" tid' <- genID @TypeIDV1 "foo" let mapping = M.fromList [(tid, tid')]- let json = encode mapping- decode json `shouldBe` Just mapping- fmap encode (decode @(Map TypeIDV1 TypeIDV1) json) `shouldBe` Just json+ let tJson = encode mapping+ decode tJson `shouldBe` Just mapping+ fmap encode (decode @(Map TypeIDV1 TypeIDV1) tJson) `shouldBe` Just tJson describe "Valid JSON value" do forM_ valid \(TestData n tid (Just pref) (Just uid)) -> it n do case decode @TypeIDV1 (fromString $ show tid) of@@ -502,6 +518,14 @@ case string2ID @TypeIDV4 "mmzk_5hjpeh96458fct8t49fnf9farw" of Left err -> expectationFailure $ "Parse error: " ++ show err Right tid -> getPrefix tid `shouldBe` "mmzk"+ it "can parse TypeIDV4 from Text" do+ case text2ID @TypeID "mmzk_00041061050r3gg28a1c60t3gf" of+ Left err -> expectationFailure $ "Parse error: " ++ show err+ Right tid -> getPrefix tid `shouldBe` "mmzk"+ it "can parse TypeIDV4 from ByteString" do+ case byteString2ID @TypeID "mmzk_00041061050r3gg28a1c60t3gf" of+ Left err -> expectationFailure $ "Parse error: " ++ show err+ Right tid -> getPrefix tid `shouldBe` "mmzk" describe "Parse TypeIDV4" do let invalidPrefixes = [ ("caps", "PREFIX")@@ -546,9 +570,9 @@ tid <- genID @TypeIDV4 "mmzk" tid' <- genID @TypeIDV4 "foo" let mapping = M.fromList [(tid, tid')]- let json = encode mapping- decode json `shouldBe` Just mapping- fmap encode (decode @(Map TypeIDV4 TypeIDV4) json) `shouldBe` Just json+ let tJson = encode mapping+ decode tJson `shouldBe` Just mapping+ fmap encode (decode @(Map TypeIDV4 TypeIDV4) tJson) `shouldBe` Just tJson describe "Valid JSON value" do forM_ valid \(TestData n tid (Just pref) (Just uid)) -> it n do case decode @TypeIDV4 (fromString $ show tid) of@@ -685,6 +709,14 @@ case string2ID @TypeIDV5 "mmzk_5hjpeh96458fct8t49fnf9farw" of Left err -> expectationFailure $ "Parse error: " ++ show err Right tid -> getPrefix tid `shouldBe` "mmzk"+ it "can parse TypeIDV5 from Text" do+ case text2ID @TypeID "mmzk_00041061050r3gg28a1c60t3gf" of+ Left err -> expectationFailure $ "Parse error: " ++ show err+ Right tid -> getPrefix tid `shouldBe` "mmzk"+ it "can parse TypeIDV5 from ByteString" do+ case byteString2ID @TypeID "mmzk_00041061050r3gg28a1c60t3gf" of+ Left err -> expectationFailure $ "Parse error: " ++ show err+ Right tid -> getPrefix tid `shouldBe` "mmzk" describe "Parse TypeIDV5" do uid <- runIO nextRandom@@ -731,9 +763,9 @@ tid <- genID @TypeIDV5 "mmzk" uid [11, 45, 14] tid' <- genID @TypeIDV5 "foo" uid [11, 45, 14] let mapping = M.fromList [(tid, tid')]- let json = encode mapping- decode json `shouldBe` Just mapping- fmap encode (decode @(Map TypeIDV5 TypeIDV5) json) `shouldBe` Just json+ let tJson = encode mapping+ decode tJson `shouldBe` Just mapping+ fmap encode (decode @(Map TypeIDV5 TypeIDV5) tJson) `shouldBe` Just tJson describe "Valid JSON value" do forM_ valid \(TestData n tid (Just pref) (Just uid)) -> it n do case decode @TypeIDV5 (fromString $ show tid) of