Advertisement
Guest User

Untitled

a guest
Oct 27th, 2016
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.49 KB | None | 0 0
  1. -- UUIDs are terrible, and I couldn't get the `uuid` package to work on Haste
  2. -- So here's something similar that I like more
  3. -- CUAD: Cute, Unique And iDentifying
  4. -- (new backronym thanks to those lovely three Irenes)
  5. -- A quad (see what I did there?) of four 32-bit words
  6. -- Canon text representation is 4 hex words separated by dashes
  7. -- e.g. 01234567-89abcdef-deadbeef-abad1dea
  8. -- Like UUIDv4, these should be random (probabilistically unique)
  9. -- Unlike UUIDv4, these have 2^6x as much randomness (128 bits, not 122)
  10. module CUAD
  11. ( CUAD,
  12. toString,
  13. fromString
  14. ) where
  15.  
  16. import Data.Char (isHexDigit, digitToInt, intToDigit, isSpace)
  17. import Data.List (unfoldr)
  18. import Data.Word (Word32)
  19.  
  20. data CUAD = CUAD Word32 Word32 Word32 Word32
  21. deriving (Ord, Eq)
  22.  
  23. chunksOf :: Int -> [a] -> [[a]]
  24. chunksOf _ [] = []
  25. chunksOf n xs = fxs : chunksOf n sxs
  26. where (fxs, sxs) = splitAt n xs
  27.  
  28. -- The string length of a 32-bit hex word
  29. wordLength :: Int
  30. wordLength = 8
  31.  
  32. -- The string length of a full CUAD
  33. cuadLength :: Int
  34. cuadLength = wordLength * 4 + 3
  35.  
  36. fromString :: String -> Maybe CUAD
  37. fromString str
  38. | all isValidWord wordStrings = Just cuad
  39. | otherwise = Nothing
  40. where
  41. wordStrings = chunksOf (wordLength + 1) ('-' : str)
  42. w1:w2:w3:w4:[] = map (\('-':word) -> readWord word) wordStrings
  43. cuad = CUAD w1 w2 w3 w4
  44.  
  45. readWord :: String -> Word32
  46. readWord = foldl (\acc digit -> acc * 16 + (fromIntegral $ digitToInt digit)) 0
  47.  
  48. showWord :: Word32 -> String
  49. showWord num = reverse $ unfoldr f (num, 0)
  50. where
  51. f (num, digitCount)
  52. | num > 0 || digitCount < wordLength =
  53. let digit = intToDigit $ fromIntegral $ num `mod` 16
  54. num' = num `div` 16
  55. digitCount' = digitCount + 1
  56. in Just (digit, (num', digitCount'))
  57. | otherwise = Nothing
  58.  
  59. isValidWord :: String -> Bool
  60. isValidWord ('-':hex) = all isHexDigit hex && length hex == wordLength
  61. isValidWord _ = False
  62.  
  63. toString :: CUAD -> String
  64. toString (CUAD w1 w2 w3 w4) = showWord w1 ++ '-' : showWord w2 ++ '-' : showWord w3 ++ '-' : showWord w4
  65.  
  66. instance Read CUAD where
  67. readsPrec _ str = case maybeCuad of
  68. Just cuad -> [(cuad, rem)]
  69. Nothing -> []
  70. where
  71. unpaddedStr = dropWhile isSpace str
  72. (cuadStr, rem) = splitAt cuadLength unpaddedStr
  73. maybeCuad = fromString cuadStr
  74.  
  75. instance Show CUAD where
  76. show = toString
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement