packages feed

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 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