ulid 0.3.2.0 → 0.3.3.0
raw patch · 5 files changed
+45/−24 lines, 5 files
Files
- README.md +19/−9
- src/Data/ULID.hs +3/−5
- src/Data/ULID/Random.hs +1/−1
- test/Data/ULIDSpec.hs +18/−2
- ulid.cabal +4/−7
README.md view
@@ -19,7 +19,7 @@ ``` -# Universally Unique Lexicographically Sortable Identifier+## Universally Unique Lexicographically Sortable Identifier UUID can be suboptimal for many uses-cases because: @@ -46,6 +46,19 @@ [Douglas Crockford's base 32]: https://www.crockford.com/base32.html +## Known Issues++- No monotonicity guarantees+ ([official spec](+ https://github.com/ulid/spec?tab=readme-ov-file#monotonicity))+- Lexicographically sorted based on the random component+ if timestamps are the same.+ This causes the sort order to be non-deterministic+ for ULIDs with the same timestamp,+ but is necessary to avoid [incorrect `Map` and `Set` behavior](+ https://github.com/haskell-github-trust/ulid/issues/15#issuecomment-2426847267).++ ## Usage A simple usage example:@@ -72,7 +85,7 @@ Example: -````haskell+```haskell module Main where import Data.ULID@@ -83,21 +96,18 @@ main :: IO () main = do- -- This default instantiation may not be sufficiently secure.- -- See the docs at- -- hackage.haskell.org/package/crypto-api-0.13.2/docs/Crypto-Random.html g <- (CR.newGenIO :: IO CR.SystemRandom) -- Generate timestamp from current time t <- TS.getULIDTimeStamp let ulid3 = case UR.mkCryptoULIDRandom g of- Left err -> error $ show err- -- use g2, …, to continue generating secure ULIDs- Right (rnd, g2) -> ULID t rnd+ Left err -> error $ show err+ -- Use g2, …, to continue generating secure ULIDs+ Right (rnd, g2) -> ULID t rnd print ulid3-````+``` ## Test Suite
src/Data/ULID.hs view
@@ -42,7 +42,8 @@ import Data.Data import Data.Hashable import Data.Monoid ((<>))-import Data.Text as T+import Data.Text (Text)+import qualified Data.Text as T import Data.Time.Clock.POSIX import GHC.Generics import System.IO.Unsafe@@ -62,10 +63,7 @@ { timeStamp :: !ULIDTimeStamp , random :: !ULIDRandom }- deriving (Eq, Typeable, Data, Generic)--instance Ord ULID where- compare (ULID ts1 _) (ULID ts2 _) = compare ts1 ts2+ deriving (Eq, Ord, Typeable, Data, Generic) instance Show ULID where show (ULID ts bytes) = show ts ++ show bytes
src/Data/ULID/Random.hs view
@@ -29,7 +29,7 @@ -- | Newtype wrapping a `ByteString` newtype ULIDRandom = ULIDRandom BS.ByteString- deriving (Eq, Typeable, Data, Generic)+ deriving (Eq, Ord, Typeable, Data, Generic) instance Show ULIDRandom where show (ULIDRandom r) = T.unpack $ B32.encode 16 . roll . BS.unpack $ r
test/Data/ULIDSpec.hs view
@@ -6,12 +6,14 @@ import qualified Data.ByteString.Lazy as LBS import Data.Char import Data.Hashable-import Data.List (nub, sort)+import Data.List (nub, sort, sortOn) import qualified System.Random as R import Data.ULID import Test.Hspec+import Data.ULID.TimeStamp (getULIDTimeStamp)+import Data.ULID.Random (getULIDRandom) spec :: Spec@@ -34,6 +36,20 @@ let l' = sort l l' `shouldBe` [show u1, show u2, show u3, show u4] + -- it should be lexicographically sortable even if the timestamps are the same+ ts <- getULIDTimeStamp+ ur1 <- getULIDRandom+ ur2 <- getULIDRandom+ ur3 <- getULIDRandom+ ur4 <- getULIDRandom++ let u5 = ULID ts ur1+ let u6 = ULID ts ur2+ let u7 = ULID ts ur3+ let u8 = ULID ts ur4++ sort [u5, u6, u7, u8] `shouldBe` sortOn show [u5, u6, u7, u8]+ -- make sure it works in internal representation too :) let ul = [u3, u2, u4, u1] let ul' = sort ul@@ -57,7 +73,7 @@ describe "ulid" $ do it "starts with 0 (at least for the foreseeable future)" $ do u1 <- getULID- head (show u1) `shouldBe` '0'+ take 1 (show u1) `shouldBe` ['0'] it "generates unique ulids in default configuration" $ do let ops = 1000
ulid.cabal view
@@ -1,5 +1,6 @@+cabal-version: 3.8 name: ulid-version: 0.3.2.0+version: 0.3.3.0 synopsis: Implementation of ULID - Universally Unique Lexicographically Sortable Identifier description: Implementation of Alizain Feerasta's ULID specification.@@ -9,15 +10,13 @@ for better efficiency and readability (5 bits per character). homepage: https://github.com/ad-si/ulid-license: BSD3+license: BSD-3-Clause license-file: LICENSE-author: Steve Kollmansberger+author: Steve Kollmansberger, Adrian Sieber maintainer: ulid@ad-si.com-copyright: 2017 Steve Kollmansberger category: Data, Codec, Database build-type: Simple extra-source-files: README.md-cabal-version: >=1.10 library@@ -52,7 +51,6 @@ test-suite ulid-test- type: exitcode-stdio-1.0 hs-source-dirs: test main-is: Spec.hs other-modules: Data.ULID.Base32Spec@@ -72,7 +70,6 @@ benchmark ulid-bench- type: exitcode-stdio-1.0 hs-source-dirs: bench main-is: Main.hs build-depends: base