-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Human exchangable identifiers and locators -- -- Human exchangable identifiers and locators @package locators @version 0.2.4.2 -- | Background -- -- We had a need for identifiers that could be used by humans. -- -- The requirement to be able to say these over the phone complicates -- matters. Most people have approached this problem by using a phonetic -- alphabet. The trouble comes when you hear people saying stuff like "A -- as in ... uh, Apple?" (should be Alpha, of course) and "U as in ... -- um, what's a word that starts with U?" It gets worse. Ever been to a -- GPG keysigning? Listen to people attempt to read out the digits of -- their key fingerprints. ...C 3 E D 0 0 0 0 0 0 0 2 B D B D... "Did you -- say 'C' or 'D'?" and "how many zeros was that?" Brutal. -- -- So what we need is a symbol set where each digit is unambigious and -- doesn't collide with the phonetics of another symbol. This package -- provides Locator16, a set of 16 letters and numbers that, when spoken -- in English, have unique pronounciation. -- -- Also included is code to work in base 62, which is simply -- ['0'-'9', 'A'-'Z', and -- 'a'-'z']. These are frequently used to express short -- codes in URL redirectors; you may find them a more useful encoding for -- expressing numbers than base 16 hexidecimal. module Data.Locator class (Ord α, Enum α, Bounded α) => Locator α locatorToDigit :: Locator α => α -> Char digitToLocator :: Locator α => Char -> α -- | 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. data English16 -- | '0' 0th Zero :: English16 -- | '1' 1st One :: English16 -- | '2' 2nd Two :: English16 -- | 'C' 3rd Charlie :: English16 -- | '4' 4th Four :: English16 -- | 'F' 5th Foxtrot :: English16 -- | 'H' 6th Hotel :: English16 -- | '7' 7th Seven :: English16 -- | '8' 8th Eight :: English16 -- | '9' 9th Nine :: English16 -- | 'K' 10th Kilo :: English16 -- | 'L' 11th Lima :: English16 -- | 'M' 12th Mike :: English16 -- | 'R' 13th Romeo :: English16 -- | 'X' 14th XRay :: English16 -- | 'Y' 15th Yankee :: English16 -- | Given a number encoded in Locator16, convert it back to an integer. fromLocator16 :: String -> Int -- | Given a number, convert it to a string in the Locator16 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. toLocator16 :: Int -> String -- | 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 --toLocator16a :: Int -> Int -> String -- | Take an arbitrary sequence of bytes, hash it with SHA1, then format as -- a short digits-long Locator16 string. -- --
-- >>> hashStringToLocator16a 6 "Hello World" -- M48HR0 --hashStringToLocator16a :: Int -> ByteString -> ByteString toBase62 :: Integer -> String fromBase62 :: String -> Integer -- | 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 -- | 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