packages feed

locators 0.3.0.3 → 0.3.0.5

raw patch · 7 files changed

+325/−372 lines, 7 filesdep +cryptondep −cryptonite

Dependencies added: crypton

Dependencies removed: cryptonite

Files

lib/Data/Locator.hs view
@@ -1,16 +1,3 @@------ Human exchangable identifiers and locators------ Copyright © 2011-2018 Operational Dynamics Consulting, Pty Ltd------ The code in this file, and the program it is a part of, is--- made available to you by its authors as open source software:--- you can redistribute it and/or modify it under the terms of--- the BSD licence.------ This code originally licenced GPLv2. Relicenced BSD3 on 2 Jan 2014.---- {-# LANGUAGE OverloadedStrings #-}  --
lib/Data/Locator/Common.hs view
@@ -1,30 +1,18 @@------ Human exchangable identifiers and locators------ Copyright © 2011-2018 Operational Dynamics Consulting, Pty Ltd------ The code in this file, and the program it is a part of, is--- made available to you by its authors as open source software:--- you can redistribute it and/or modify it under the terms of--- the BSD licence.------ This code originally licenced GPLv2. Relicenced BSD3 on 2 Jan 2014.---+{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE TypeApplications #-} -module Data.Locator.Common-  ( Locator(..)-  , represent-  , value-  , toLocatorUnique-  , multiply-  , fromLocator-  , concatToInteger-  , digest-  ) where+module Data.Locator.Common (+    Locator (..),+    represent,+    value,+    toLocatorUnique,+    multiply,+    fromLocator,+    concatToInteger,+    digest,+) where  import Prelude hiding (toInteger) @@ -40,7 +28,6 @@     locatorToDigit :: α -> Char     digitToLocator :: Char -> α - represent :: Locator α => α -> Int -> Char represent (_ :: α) n =     locatorToDigit $ (toEnum n :: α)@@ -56,41 +43,39 @@     fromEnum $ (digitToLocator c :: α)  ----- | Represent a number in Locator16a format. This uses the Locator16 symbol--- set, and additionally specifies that no symbol can be repeated. The /a/ in--- Locator16a represents that this transformation is done on the cheap; when--- converting if we end up with \'9\' \'9\' we simply pick the subsequent digit--- in the enum, in this case getting you \'9\' \'K\'.------ Note that the transformation is /not/ reversible. A number like @4369@--- (which is @0x1111@, incidentally) encodes as @12C4@. So do @4370@, @4371@,--- and @4372@. The point is not uniqueness, but readibility in adverse--- conditions. So while you can count locators, they don't map continuously to--- base10 integers.------ The first argument is the number of digits you'd like in the locator; if the--- number passed in is less than 16^limit, then the result will be padded.------ >>> toLocator16a 6 4369--- 12C40F---++{- |+Represent a number in Locator16a format. This uses the Locator16 symbol+set, and additionally specifies that no symbol can be repeated. The /a/ in+Locator16a represents that this transformation is done on the cheap; when+converting if we end up with \'9\' \'9\' we simply pick the subsequent digit+in the enum, in this case getting you \'9\' \'K\'.++Note that the transformation is /not/ reversible. A number like @4369@+(which is @0x1111@, incidentally) encodes as @12C4@. So do @4370@, @4371@,+and @4372@. The point is not uniqueness, but readibility in adverse+conditions. So while you can count locators, they don't map continuously to+base10 integers.++The first argument is the number of digits you'd like in the locator; if the+number passed in is less than 16^limit, then the result will be padded.++>>> toLocator16a 6 4369+12C40F+-} toLocatorUnique :: Locator α => Int -> Int -> α -> String toLocatorUnique limit n (_ :: α) =-  let-    n' = abs n-    ls = convert n' (replicate limit (minBound @α))-    (_,us) = mapAccumL uniq Set.empty ls-  in-    map locatorToDigit (take limit us)+    let n' = abs n+        ls = convert n' (replicate limit (minBound @α))+        (_, us) = mapAccumL uniq Set.empty ls+     in map locatorToDigit (take limit us)   where     convert :: Locator α => Int -> [α] -> [α]     convert 0 xs = xs     convert i xs =-      let-        (d,r) = divMod i 16-        x = toEnum r-      in-        convert d (x:xs)+        let (d, r) = divMod i 16+            x = toEnum r+         in convert d (x : xs)      uniq :: Locator α => Set α -> α -> (Set α, α)     uniq s x =@@ -106,14 +91,12 @@  multiply :: Locator α => α -> Int -> Char -> Int multiply (locator :: a) acc c =-  let-    base = fromEnum (maxBound @a) + 1-  in-    (acc * base) + (value locator c)+    let base = fromEnum (maxBound @a) + 1+     in (acc * base) + (value locator c)  --+ -- | Given a number encoded as a Locator, convert it back to an integer.--- fromLocator :: Locator α => α -> String -> Int fromLocator locator ss =     foldl (multiply locator) 0 ss@@ -131,8 +114,7 @@ digest ws =     i   where-    i  = concatToInteger h-    h  = B.unpack h'+    i = concatToInteger h+    h = B.unpack h'     h' = Crypto.hash x' :: Crypto.Digest Crypto.SHA1     x' = S.pack ws-
lib/Data/Locator/English16.hs view
@@ -1,34 +1,21 @@------ Human exchangable identifiers and locators------ Copyright © 2011-2018 Operational Dynamics Consulting, Pty Ltd------ The code in this file, and the program it is a part of, is--- made available to you by its authors as open source software:--- you can redistribute it and/or modify it under the terms of--- the BSD licence.------ This code originally licenced GPLv2. Relicenced BSD3 on 2 Jan 2014.---+{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE TypeApplications #-} -module Data.Locator.English16-  ( Locator(..)-  , English16(..)-  , fromEnglish16-  , toEnglish16-  , toEnglish16a-  , hashStringToEnglish16a-+module Data.Locator.English16 (+    Locator (..),+    English16 (..),+    fromEnglish16,+    toEnglish16,+    toEnglish16a,+    hashStringToEnglish16a,     -- Deprecated-  , fromLocator16-  , toLocator16-  , toLocator16a-  , hashStringToLocator16a-  ) where+    fromLocator16,+    toLocator16,+    toLocator16a,+    hashStringToLocator16a,+) where  import Prelude hiding (toInteger) @@ -42,20 +29,23 @@ import Data.Locator.Common  ----- | A symbol set with sixteen uniquely pronounceable digits.------ The fact there are sixteen symbols is more an indication of a certain degree--- of bullheaded-ness on the part of the author, and less of any kind of actual--- requirement. We might have a slighly better readback score if we dropped to--- 15 or 14 unique characters. It does mean you can match up with hexidecimal,--- which is not entirely without merit.------ The grouping of letters and numbers was the hard part; having come up with--- the set and deconflicted the choices, the ordering is then entirely--- arbitrary. Since there are some numbers, might as well have them at the same--- place they correspond to in base 10; the letters were then allocated in--- alpha order in the remaining slots.---++{- |+A symbol set with sixteen uniquely pronounceable digits.++The fact there are sixteen symbols is more an indication of a certain degree+of bullheaded-ness on the part of the author, and less of any kind of actual+requirement. We might have a slighly better readback score if we dropped to+15 or 14 unique characters. It does mean you can match up with hexidecimal,+which is not entirely without merit.++The grouping of letters and numbers was the hard part; having come up with+the set and deconflicted the choices, the ordering is then entirely+arbitrary. Since there are some numbers, might as well have them at the same+place they correspond to in base 10; the letters were then allocated in alpha+order in the remaining slots.+-}+ {-         -- 0 Conflicts with @\'O\'@ obviously, and @\'Q\'@ often enough         --@@ -90,44 +80,60 @@         -- usual reason of being similar to @\'1\'@. -} data English16-    = Zero      -- ^ @\'0\'@ /0th/-    | One       -- ^ @\'1\'@ /1st/-    | Two       -- ^ @\'2\'@ /2nd/-    | Charlie   -- ^ @\'C\'@ /3rd/-    | Four      -- ^ @\'4\'@ /4th/-    | Foxtrot   -- ^ @\'F\'@ /5th/-    | Hotel     -- ^ @\'H\'@ /6th/-    | Seven     -- ^ @\'7\'@ /7th/-    | Eight     -- ^ @\'8\'@ /8th/-    | Nine      -- ^ @\'9\'@ /9th/-    | Kilo      -- ^ @\'K\'@ /10th/-    | Lima      -- ^ @\'L\'@ /11th/-    | Mike      -- ^ @\'M\'@ /12th/-    | Romeo     -- ^ @\'R\'@ /13th/-    | XRay      -- ^ @\'X\'@ /14th/-    | Yankee    -- ^ @\'Y\'@ /15th/+    = -- | @\'0\'@ /0th/+      Zero+    | -- | @\'1\'@ /1st/+      One+    | -- | @\'2\'@ /2nd/+      Two+    | -- | @\'C\'@ /3rd/+      Charlie+    | -- | @\'4\'@ /4th/+      Four+    | -- | @\'F\'@ /5th/+      Foxtrot+    | -- | @\'H\'@ /6th/+      Hotel+    | -- | @\'7\'@ /7th/+      Seven+    | -- | @\'8\'@ /8th/+      Eight+    | -- | @\'9\'@ /9th/+      Nine+    | -- | @\'K\'@ /10th/+      Kilo+    | -- | @\'L\'@ /11th/+      Lima+    | -- | @\'M\'@ /12th/+      Mike+    | -- | @\'R\'@ /13th/+      Romeo+    | -- | @\'X\'@ /14th/+      XRay+    | -- | @\'Y\'@ /15th/+      Yankee     deriving (Eq, Ord, Enum, Bounded)  instance Locator English16 where     locatorToDigit :: English16 -> Char     locatorToDigit x =         case x of-            Zero    -> '0'-            One     -> '1'-            Two     -> '2'+            Zero -> '0'+            One -> '1'+            Two -> '2'             Charlie -> 'C'-            Four    -> '4'+            Four -> '4'             Foxtrot -> 'F'-            Hotel   -> 'H'-            Seven   -> '7'-            Eight   -> '8'-            Nine    -> '9'-            Kilo    -> 'K'-            Lima    -> 'L'-            Mike    -> 'M'-            Romeo   -> 'R'-            XRay    -> 'X'-            Yankee  -> 'Y'+            Hotel -> 'H'+            Seven -> '7'+            Eight -> '8'+            Nine -> '9'+            Kilo -> 'K'+            Lima -> 'L'+            Mike -> 'M'+            Romeo -> 'R'+            XRay -> 'X'+            Yankee -> 'Y'      digitToLocator :: Char -> English16     digitToLocator c =@@ -148,7 +154,7 @@             'R' -> Romeo             'X' -> XRay             'Y' -> Yankee-            _   -> error "Illegal digit"+            _ -> error "Illegal digit"  instance Show English16 where     show x = [c]@@ -156,54 +162,54 @@         c = locatorToDigit x  ----- | Given a number, convert it to a string in the English16 base 16 symbol--- alphabet. You can use this as a replacement for the standard \'0\'-\'9\'--- \'A\'-\'F\' symbols traditionally used to express hexidemimal, though really--- the fact that we came up with 16 total unique symbols was a nice--- co-incidence, not a requirement.---++{- |+Given a number, convert it to a string in the English16 base 16 symbol+alphabet. You can use this as a replacement for the standard \'0\'-\'9\'+\'A\'-\'F\' symbols traditionally used to express hexidemimal, though really+the fact that we came up with 16 total unique symbols was a nice+co-incidence, not a requirement.+-} toEnglish16 :: Int -> String toEnglish16 x =     showIntAtBase 16 (represent Yankee) x ""  ----- | Represent a number in English16a format. This uses the Locator16 symbol--- set, and additionally specifies that no symbol can be repeated. The /a/ in--- Locator16a represents that this transformation is done on the cheap; when--- converting if we end up with \'9\' \'9\' we simply pick the subsequent digit--- in the enum, in this case getting you \'9\' \'K\'.------ Note that the transformation is /not/ reversible. A number like @4369@--- (which is @0x1111@, incidentally) encodes as @12C4@. So do @4370@, @4371@,--- and @4372@. The point is not uniqueness, but readibility in adverse--- conditions. So while you can count locators, they don't map continuously to--- base10 integers.------ The first argument is the number of digits you'd like in the locator; if the--- number passed in is less than 16^limit, then the result will be padded.------ >>> toEnglish16a 6 4369--- 12C40F---++{- |+Represent a number in English16a format. This uses the Locator16 symbol+set, and additionally specifies that no symbol can be repeated. The /a/ in+Locator16a represents that this transformation is done on the cheap; when+converting if we end up with \'9\' \'9\' we simply pick the subsequent digit+in the enum, in this case getting you \'9\' \'K\'.++Note that the transformation is /not/ reversible. A number like @4369@+(which is @0x1111@, incidentally) encodes as @12C4@. So do @4370@, @4371@,+and @4372@. The point is not uniqueness, but readibility in adverse+conditions. So while you can count locators, they don't map continuously to+base10 integers.++The first argument is the number of digits you'd like in the locator; if the+number passed in is less than 16^limit, then the result will be padded.++>>> toEnglish16a 6 4369+12C40F+-} toEnglish16a :: Int -> Int -> String toEnglish16a limit n-  | limit > 16 = error "Can only request a maximum of 16 English16a characters, not " ++ (show limit)-  | otherwise  =-  let-    n' = abs n-    ls = convert n' (replicate limit minBound)       :: [English16]-    (_,us) = mapAccumL uniq Set.empty ls-  in-    map locatorToDigit (take limit us)+    | limit > 16 = error "Can only request a maximum of 16 English16a characters, not " ++ (show limit)+    | otherwise =+        let n' = abs n+            ls = convert n' (replicate limit minBound) :: [English16]+            (_, us) = mapAccumL uniq Set.empty ls+         in map locatorToDigit (take limit us)   where     convert :: Locator α => Int -> [α] -> [α]     convert 0 xs = xs     convert i xs =-      let-        (d,r) = divMod i 16-        x = toEnum r-      in-        convert d (x:xs)+        let (d, r) = divMod i 16+            x = toEnum r+         in convert d (x : xs)      uniq :: Locator α => Set α -> α -> (Set α, α)     uniq s x =@@ -218,33 +224,32 @@             else succ x  --+ -- | Given a number encoded in Locator16, convert it back to an integer.--- fromEnglish16 :: [Char] -> Int fromEnglish16 ss =     foldl (multiply Yankee) 0 ss  ----- | Take an arbitrary sequence of bytes, hash it with SHA1, then format as a--- short @digits@-long Locator16 string.------ >>> hashStringToLocator16a 6 "Hello World"--- M48HR0---++{- |+Take an arbitrary sequence of bytes, hash it with SHA1, then format as a+short @digits@-long Locator16 string.++>>> hashStringToLocator16a 6 "Hello World"+M48HR0+-} hashStringToEnglish16a :: Int -> ByteString -> ByteString hashStringToEnglish16a limit s' =-  let-    s  = S.unpack s'-    n  = digest s               -- SHA1 hash-    r  = mod n upperBound       -- trim to specified number of base 16 chars-    x  = toLocator16a limit r   -- express in locator16-    b' = S.pack x-  in-    b'+    let s = S.unpack s'+        n = digest s -- SHA1 hash+        r = mod n upperBound -- trim to specified number of base 16 chars+        x = toLocator16a limit r -- express in locator16+        b' = S.pack x+     in b'   where     upperBound = 16 ^ limit - toLocator16 :: Int -> String toLocator16 = toEnglish16 {-# DEPRECATED toLocator16 "Use toEnglish16 instead" #-}@@ -256,7 +261,6 @@ fromLocator16 :: [Char] -> Int fromLocator16 = fromEnglish16 {-# DEPRECATED fromLocator16 "Use fromEnglish16 instead" #-}-  hashStringToLocator16a :: Int -> ByteString -> ByteString hashStringToLocator16a = hashStringToEnglish16a
lib/Data/Locator/Hashes.hs view
@@ -1,26 +1,12 @@------ Human exchangable identifiers and locators------ Copyright © 2011-2017 Operational Dynamics Consulting, Pty Ltd------ The code in this file, and the program it is a part of, is--- made available to you by its authors as open source software:--- you can redistribute it and/or modify it under the terms of--- the BSD licence.------ This code originally licenced GPLv2. Relicenced BSD3 on 2 Jan 2014.---- {-# LANGUAGE OverloadedStrings #-}  module Data.Locator.Hashes (     toBase62,     fromBase62,     padWithZeros,-    hashStringToBase62+    hashStringToBase62, ) where - import Prelude hiding (toInteger)  import Crypto.Hash as Crypto@@ -47,13 +33,14 @@     showIntAtBase 62 represent x ""  ----- | Utility function to prepend \'0\' characters to a string representing a--- number. This allows you to ensure a fixed width for numbers that are less--- than the desired width in size. This comes up frequently when representing--- numbers in other bases greater than 10 as they are inevitably presented as--- text, and not having them evenly justified can (at best) be ugly and (at--- worst) actually lead to parsing and conversion bugs.---++{- | Utility function to prepend \'0\' characters to a string representing a+ number. This allows you to ensure a fixed width for numbers that are less+ than the desired width in size. This comes up frequently when representing+ numbers in other bases greater than 10 as they are inevitably presented as+ text, and not having them evenly justified can (at best) be ugly and (at+ worst) actually lead to parsing and conversion bugs.+-} padWithZeros :: Int -> String -> String padWithZeros digits str =     pad ++ str@@ -61,7 +48,6 @@     pad = take len (replicate digits '0')     len = digits - length str - value :: Char -> Int value c     | isDigit c = ord c - 48@@ -77,43 +63,40 @@ fromBase62 ss =     foldl multiply 0 ss - concatToInteger :: [Word8] -> Integer concatToInteger bytes =     foldl fn 0 bytes   where     fn acc b = (acc * 256) + (fromIntegral b) - digest :: String -> Integer digest ws =     i   where-    i  = concatToInteger h-    h  = B.unpack h'+    i = concatToInteger h+    h = B.unpack h'     h' = Crypto.hash x' :: Crypto.Digest Crypto.SHA1     x' = S.pack ws - ----- | Take an arbitrary string, hash it, then pad it with zeros up to be a--- @digits@-long string in base 62.------ You may be interested to know that the 160-bit SHA1 hash used here can be--- expressed without loss as 27 digits of base 62, for example:------ >>> hashStringToBase62 27 "Hello World"--- 1T8Sj4C5jVU6iQXCwCwJEPSWX6u---++{- | Take an arbitrary string, hash it, then pad it with zeros up to be a+ @digits@-long string in base 62.++ You may be interested to know that the 160-bit SHA1 hash used here can be+ expressed without loss as 27 digits of base 62, for example:++ >>> hashStringToBase62 27 "Hello World"+ 1T8Sj4C5jVU6iQXCwCwJEPSWX6u+-} hashStringToBase62 :: Int -> ByteString -> ByteString hashStringToBase62 digits s' =     r'   where     s = S.unpack s'-    n  = digest s               -- SHA1 hash+    n = digest s -- SHA1 hash     limit = 62 ^ digits-    x  = mod n limit            -- trim to specified number base62 chars+    x = mod n limit -- trim to specified number base62 chars     str = toBase62 x-    r  = padWithZeros digits str  -- convert to String+    r = padWithZeros digits str -- convert to String     r' = S.pack r-
lib/Data/Locator/Latin25.hs view
@@ -1,26 +1,13 @@------ Human exchangable identifiers and locators------ Copyright © 2011-2018 Operational Dynamics Consulting, Pty Ltd------ The code in this file, and the program it is a part of, is--- made available to you by its authors as open source software:--- you can redistribute it and/or modify it under the terms of--- the BSD licence.------ This code originally licenced GPLv2. Relicenced BSD3 on 2 Jan 2014.-----{-# LANGUAGE OverloadedStrings   #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-} -module Data.Locator.Latin25-  ( Latin25(..)-  , toLatin25-  , fromLatin25-  , hashStringToLatin25-  ) where+module Data.Locator.Latin25 (+    Latin25 (..),+    toLatin25,+    fromLatin25,+    hashStringToLatin25,+) where  import Prelude hiding (toInteger) @@ -31,12 +18,13 @@ import Data.Locator.Common import Data.Locator.Hashes (padWithZeros) ------ | A symbol set with twenty-five visually distinct characters.------ These are not protected against similar pronounciations; if you need to--- read your identifiers /aloud/ use 'English16' instead.---+{- |+A symbol set with twenty-five visually distinct characters.++These are not protected against similar pronounciations; if you need to+read your identifiers /aloud/ use 'English16' instead.+-}+ {-      --  | Two       -- Obvious conflict with Z@@ -44,7 +32,7 @@     --  | Six       -- Too close to G     --  | Bravo     -- Too close to 8     --  | Delta     -- Shape of D too close to O-    --  | Foxtrot   -- A bit close to E, and since we've included S, skip+    --  | Foxtrot   -- Excluded because too close to E     --  | India     -- Too close to 1 and J     --  | Oscar     -- Obvious conflict with 0     --  | Quebec    -- The tail on Q is too easy to miss, thereby colliding with O/0@@ -53,61 +41,86 @@  -} data Latin25-    = Zero'     -- ^ @\'0\'@ /0th/-    | One'      -- ^ @\'1\'@ /1st/-    | Three'    -- ^ @\'3\'@ /2nd/-    | Four'     -- ^ @\'4\'@ /3rd/-    | Seven'    -- ^ @\'7\'@ /4th/-    | Eight'    -- ^ @\'8\'@ /5th/-    | Nine'     -- ^ @\'9\'@ /6th/-    | Alpha'    -- ^ @\'A\'@ /7th/-    | Charlie'  -- ^ @\'C\'@ /8th/-    | Echo'     -- ^ @\'E\'@ /9th/-    | Golf'     -- ^ @\'G\'@ /10th/-    | Hotel'    -- ^ @\'H\'@ /11th/-    | Juliet'   -- ^ @\'J\'@ /12th/-    | Kilo'     -- ^ @\'K\'@ /13th/-    | Lima'     -- ^ @\'L\'@ /14th/-    | Mike'     -- ^ @\'M\'@ /15th/-    | November' -- ^ @\'N\'@ /16th/-    | Papa'     -- ^ @\'P\'@ /17th/-    | Sierra'   -- ^ @\'S\'@ /18th/-    | Tango'    -- ^ @\'T\'@ /19th/-    | Victor'   -- ^ @\'V\'@ /20th/-    | Whiskey'  -- ^ @\'W\'@ /21st/-    | XRay'     -- ^ @\'X\'@ /22nd/-    | Yankee'   -- ^ @\'Y\'@ /23rd/-    | Zulu'     -- ^ @\'Z\'@ /24th/+    = -- | @\'0\'@ /0th/+      Zero'+    | -- | @\'1\'@ /1st/+      One'+    | -- | @\'3\'@ /2nd/+      Three'+    | -- | @\'4\'@ /3rd/+      Four'+    | -- | @\'7\'@ /4th/+      Seven'+    | -- | @\'8\'@ /5th/+      Eight'+    | -- | @\'9\'@ /6th/+      Nine'+    | -- | @\'A\'@ /7th/+      Alpha'+    | -- | @\'C\'@ /8th/+      Charlie'+    | -- | @\'E\'@ /9th/+      Echo'+    | -- | @\'G\'@ /10th/+      Golf'+    | -- | @\'H\'@ /11th/+      Hotel'+    | -- | @\'J\'@ /12th/+      Juliet'+    | -- | @\'K\'@ /13th/+      Kilo'+    | -- | @\'L\'@ /14th/+      Lima'+    | -- | @\'M\'@ /15th/+      Mike'+    | -- | @\'N\'@ /16th/+      November'+    | -- | @\'P\'@ /17th/+      Papa'+    | -- | @\'S\'@ /18th/+      Sierra'+    | -- | @\'T\'@ /19th/+      Tango'+    | -- | @\'V\'@ /20th/+      Victor'+    | -- | @\'W\'@ /21st/+      Whiskey'+    | -- | @\'X\'@ /22nd/+      XRay'+    | -- | @\'Y\'@ /23rd/+      Yankee'+    | -- | @\'Z\'@ /24th/+      Zulu'     deriving (Eq, Ord, Enum, Bounded)  instance Locator Latin25 where     locatorToDigit x =         case x of-            Zero'   -> '0'-            One'    -> '1'-            Three'  -> '3'-            Four'   -> '4'-            Seven'  -> '7'-            Eight'  -> '8'-            Nine'   -> '9'-            Alpha'  -> 'A'+            Zero' -> '0'+            One' -> '1'+            Three' -> '3'+            Four' -> '4'+            Seven' -> '7'+            Eight' -> '8'+            Nine' -> '9'+            Alpha' -> 'A'             Charlie' -> 'C'-            Echo'   -> 'E'-            Golf'   -> 'G'-            Hotel'  -> 'H'+            Echo' -> 'E'+            Golf' -> 'G'+            Hotel' -> 'H'             Juliet' -> 'J'-            Kilo'   -> 'K'-            Lima'   -> 'L'-            Mike'   -> 'M'+            Kilo' -> 'K'+            Lima' -> 'L'+            Mike' -> 'M'             November' -> 'N'-            Papa'   -> 'P'+            Papa' -> 'P'             Sierra' -> 'S'-            Tango'  -> 'T'+            Tango' -> 'T'             Victor' -> 'V'-            Whiskey'-> 'W'-            XRay'   -> 'X'+            Whiskey' -> 'W'+            XRay' -> 'X'             Yankee' -> 'Y'-            Zulu'   -> 'Z'+            Zulu' -> 'Z'      digitToLocator :: Char -> Latin25     digitToLocator c =@@ -137,8 +150,7 @@             'X' -> XRay'             'Y' -> Yankee'             'Z' -> Zulu'-            _   -> error "Illegal digit"-+            _ -> error "Illegal digit"  instance Show Latin25 where     show x = [c]@@ -146,41 +158,43 @@         c = locatorToDigit x  ----- | Given a number, convert it to a string in the Latin25 base 25 symbol--- alphabet. This is useful for primary keys and object identifiers that you--- need to scan for in log output, for example.---++{- |+Given a number, convert it to a string in the Latin25 base 25 symbol+alphabet. This is useful for primary keys and object identifiers that you+need to scan for in log output, for example.+-} toLatin25 :: Int -> String toLatin25 x =     showIntAtBase 25 (represent Zulu') x ""  --+ -- | Given a number encoded in Locator16, convert it back to an integer.--- fromLatin25 :: String -> Int fromLatin25 ss =     foldl (multiply Zulu') 0 ss  ----- | Take an arbitrary sequence of bytes, hash it with SHA1, then format as a--- short @limit@-long Latin25 string.------ >>> hashStringToLatin25 5 "You'll get used to it. Or, you'll have a psychotic episode"--- XSAV1------ 17 characters is the widest hash you can request.---++{- |+Take an arbitrary sequence of bytes, hash it with SHA1, then format as a+short @limit@-long Latin25 string.++>>> hashStringToLatin25 5 "You'll get used to it. Or, you'll have a psychotic episode"+SG8XP++17 characters is the widest hash you can request.+-} hashStringToLatin25 :: Int -> ByteString -> ByteString hashStringToLatin25 limit s'-  | limit > 17 = error "Can only request a maximum width of 17, sorry"-  | otherwise  =-  let-    s  = S.unpack s'-    n  = digest s               -- SHA1 hash-    r  = mod n upperBound       -- trim to specified number of base 25 chars-    x  = toLatin25 r            -- express in Latin25-    b' = S.pack (padWithZeros limit x)-  in-    b'+    | limit > 17 = error "Can only request a maximum width of 17, sorry"+    | otherwise =+        let s = S.unpack s'+            n = digest s -- SHA1 hash+            r = mod n upperBound -- trim to specified number of base 25 chars+            x = toLatin25 r -- express in Latin25+            b' = S.pack (padWithZeros limit x)+         in b'   where     upperBound = 25 ^ limit
locators.cabal view
@@ -1,6 +1,6 @@ cabal-version:       1.24 name:                locators-version:             0.3.0.3+version:             0.3.0.5 synopsis:            Human exchangable identifiers and locators license:             MIT license-file:        LICENSE@@ -13,9 +13,9 @@  author:              Andrew Cowie <istathar@gmail.com> maintainer:          Andrew Cowie <istathar@gmail.com>-copyright:           © 2013-2020 Athae Eredh Siniath and Others+copyright:           © 2013-2024 Athae Eredh Siniath and Others category:            Other-tested-with:         GHC == 8.8.3+tested-with:         GHC == 9.6.5 stability:           experimental  build-type:          Simple@@ -27,7 +27,7 @@                      memory,                      bytestring,                      containers,-                     cryptonite+                     crypton    hs-source-dirs:    lib   include-dirs:      .@@ -38,7 +38,6 @@                      Data.Locator.English16                      Data.Locator.Latin25 -   ghc-options:       -Wall                      -Wwarn                      -fwarn-tabs@@ -60,7 +59,7 @@                      QuickCheck,                      bytestring,                      containers,-                     cryptonite,+                     crypton,                      locators    hs-source-dirs:    tests@@ -80,7 +79,7 @@  source-repository    head   type:              git-  location:          git@github.com:aesiniath/locators.git+  location:          git@github.com:aesiniath/locators-haskell.git   -- vim: set tabstop=21 expandtab:
tests/TestSuite.hs view
@@ -1,15 +1,5 @@------ Human exchangable identifiers and locators------ Copyright © 2013-2018 Operational Dynamics Consulting, Pty Ltd------ The code in this file, and the program it is a part of, is--- made available to you by its authors as open source software:--- you can redistribute it and/or modify it under the terms of--- the BSD licence.---- {-# LANGUAGE OverloadedStrings #-}+ {-# OPTIONS -fno-warn-unused-imports #-} {-# OPTIONS -fno-warn-orphans #-} {-# OPTIONS -fno-warn-type-defaults #-}@@ -18,9 +8,9 @@ module TestSuite where  import Control.Exception (evaluate)+import Test.HUnit import Test.Hspec import Test.Hspec.QuickCheck-import Test.HUnit import Test.QuickCheck (elements, property) import Test.QuickCheck.Arbitrary (Arbitrary, arbitrary) @@ -58,18 +48,14 @@     describe "Hashes" $ do         testPaddingRefactored - testRoundTripEnglish16 =     prop "safe conversion to/from English16" prop_English16  prop_English16 :: Int -> Bool prop_English16 i =-  let-    n = abs i-    decoded = fromEnglish16 (toEnglish16 n)-  in-    n == decoded-+    let n = abs i+        decoded = fromEnglish16 (toEnglish16 n)+     in n == decoded  -- -- Have to do these manually, since Locator16a is not round-trip safe.@@ -90,15 +76,15 @@     it "correctly pads strings" $ do         padWithZeros 5 "1" `shouldBe` "00001"         padWithZeros 5 "123456" `shouldBe` "123456"-        (padWithZeros 11 . toBase62 $ 2^64) `shouldBe` "LygHa16AHYG"-        (hashStringToBase62 11 . S.pack . show $ 2^64) `shouldBe` "k8SQgkJtxLo"+        (padWithZeros 11 . toBase62 $ 2 ^ 64) `shouldBe` "LygHa16AHYG"+        (hashStringToBase62 11 . S.pack . show $ 2 ^ 64) `shouldBe` "k8SQgkJtxLo"  testNegativeNumbers =     it "doesn't explode if fed a negative number" $ do         toEnglish16a 1 (-1) `shouldBe` "1"  testKnownLatin25 =-    it "base 25 is correct" $ do+    it "base 26 is correct" $ do         toLatin25 0 `shouldBe` "0"         toLatin25 1 `shouldBe` "1"         toLatin25 24 `shouldBe` "Z"@@ -109,12 +95,10 @@  prop_Latin25 :: Int -> Bool prop_Latin25 i =-  let-    n = abs i-    encoded = toLatin25 n-    decoded = fromLatin25 encoded-  in-    n == decoded+    let n = abs i+        encoded = toLatin25 n+        decoded = fromLatin25 encoded+     in n == decoded  testHashLatin25 =     it "hashToLatin25 generates an appropriate hash" $ do