base91 1.1.0 → 2.0.0
raw patch · 12 files changed
+89/−276 lines, 12 filesdep +mono-traversablePVP ok
version bump matches the API change (PVP)
Dependencies added: mono-traversable
API changes (from Hackage documentation)
- Codec.Binary.Base91.ByteString: decode :: [Char] -> ByteString
- Codec.Binary.Base91.ByteString: encode :: ByteString -> [Char]
- Codec.Binary.Base91.ByteString: instance Applicative' ByteString
- Codec.Binary.Base91.ByteString: instance Foldable' ByteString
- Codec.Binary.Base91.ByteString.Lazy: decode :: [Char] -> ByteString
- Codec.Binary.Base91.ByteString.Lazy: encode :: ByteString -> [Char]
- Codec.Binary.Base91.ByteString.Lazy: instance Applicative' ByteString
- Codec.Binary.Base91.ByteString.Lazy: instance Foldable' ByteString
- Codec.Binary.Base91.Control: class Monoid a => Applicative' a where type family Item a :: *
- Codec.Binary.Base91.Control: class Foldable' f where type family Element f :: *
- Codec.Binary.Base91.Control: fold' :: Foldable' f => (x -> Element f -> x) -> x -> f -> x
- Codec.Binary.Base91.Control: instance (Applicative a, Monoid (a i)) => Applicative' (a i)
- Codec.Binary.Base91.Control: instance Foldable f => Foldable' (f e)
- Codec.Binary.Base91.Control: pure' :: Applicative' a => Item a -> a
- Codec.Binary.Base91.Efficient: decode :: Text -> ByteString
- Codec.Binary.Base91.Efficient: encode :: ByteString -> Text
- Codec.Binary.Base91.Efficient.Lazy: decode :: Text -> ByteString
- Codec.Binary.Base91.Efficient.Lazy: encode :: ByteString -> Text
- Codec.Binary.Base91.String: decode :: String -> [Word8]
- Codec.Binary.Base91.String: encode :: [Word8] -> String
- Codec.Binary.Base91.Text: decode :: Text -> [Word8]
- Codec.Binary.Base91.Text: encode :: [Word8] -> Text
- Codec.Binary.Base91.Text: instance Applicative' Text
- Codec.Binary.Base91.Text: instance Foldable' Text
- Codec.Binary.Base91.Text.Lazy: decode :: Text -> [Word8]
- Codec.Binary.Base91.Text.Lazy: encode :: [Word8] -> Text
- Codec.Binary.Base91.Text.Lazy: instance Applicative' Text
- Codec.Binary.Base91.Text.Lazy: instance Foldable' Text
- Codec.Binary.Base91: decode :: (Foldable' i, Element i ~ Char, Applicative' o, Item o ~ Word8) => i -> o
+ Codec.Binary.Base91: decode :: (Input i Char, Output o Word8) => i -> o
- Codec.Binary.Base91: encode :: (Foldable' i, Element i ~ Word8, Applicative' o, Item o ~ Char) => i -> o
+ Codec.Binary.Base91: encode :: (Input i Word8, Output o Char) => i -> o
Files
- Codec/Binary/Base91.hs +38/−15
- Codec/Binary/Base91/ByteString.hs +0/−29
- Codec/Binary/Base91/ByteString/Lazy.hs +0/−29
- Codec/Binary/Base91/Control.hs +0/−29
- Codec/Binary/Base91/Efficient.hs +0/−18
- Codec/Binary/Base91/Efficient/Lazy.hs +0/−18
- Codec/Binary/Base91/String.hs +0/−15
- Codec/Binary/Base91/Text.hs +0/−29
- Codec/Binary/Base91/Text/Lazy.hs +0/−29
- Main.hs +6/−5
- Test.hs +39/−33
- base91.cabal +6/−27
Codec/Binary/Base91.hs view
@@ -1,22 +1,45 @@ -- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more. -- Informed by Mario Rodriguez's C++ implementation. +{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} module Codec.Binary.Base91 (alphabet, decode, encode) where -import Codec.Binary.Base91.Control (Applicative' (..), Foldable' (..)) import Data.Bits ((.&.), (.|.), shiftL, shiftR) import Data.Char (ord)-import Data.Monoid (mappend, mconcat, mempty)+import Data.Monoid (Monoid, mappend, mconcat, mempty)+import Data.MonoTraversable (Element, MonoFoldable, MonoPointed, ofoldl', opoint) import Data.Word (Word8) +type Input i e = (MonoFoldable i, Element i ~ e)+type Output o e = (MonoPointed o, Element o ~ e, Monoid o) --- | Generically encodes a 'Word8' sequence to a 'Char' sequence in Base91 form.-encode :: forall i o. (Foldable' i, Element i ~ Word8, Applicative' o, Item o ~ Char) => i -> o-encode input = g . fold' f (0, 0, mempty) $ input where+{-+encodeToString :: Input i Word8 => i -> [Char]+encodeToString = encode +decodeToBytes :: Input i Char => i -> [Word8]+decodeToBytes = decode++encodeBytes :: Output o Char => [Word8] -> o+encodeBytes = encode++decodeString :: Output o Word8 => [Char] -> o+decodeString = decode++encodeBytesToString :: [Word8] -> [Char]+encodeBytesToString = encode++decodeStringToBytes :: [Char] -> [Word8]+decodeStringToBytes = decode+-}++-- | Encodes a 'Word8' input sequence to a 'Char' output sequence in Base91 form; the opposite of 'decode'.+encode :: forall i o. (Input i Word8, Output o Char) => i -> o+encode input = g . ofoldl' f (0, 0, mempty) $ input where+ f :: (Int, Int, o) -> Word8 -> (Int, Int, o) f (queue, nbits, output) w = let queue' = queue .|. (fromWord8 w `shiftL` nbits)@@ -27,20 +50,20 @@ (v, q, n) = if value > 88 then (value, queue' `shiftR` 13, nbits' - 13) else (value', queue' `shiftR` 14, nbits' - 14)- x = pure' $ alphabet !! (v `mod` 91)- y = pure' $ alphabet !! (v `div` 91)+ x = opoint $ alphabet !! (v `mod` 91)+ y = opoint $ alphabet !! (v `div` 91) in (q, n, mconcat [output, x, y]) g :: (Int, Int, o) -> o g (_, 0, output) = output g (queue, nbits, output) = mconcat [output, x, y]- where x = pure' $ alphabet !! (queue `mod` 91)- y | nbits > 7 || queue > 90 = pure' $ alphabet !! (queue `div` 91)+ where x = opoint $ alphabet !! (queue `mod` 91)+ y | nbits > 7 || queue > 90 = opoint $ alphabet !! (queue `div` 91) | otherwise = mempty --- | Generically decodes a 'Word8' sequence from a 'Char' sequence in Base91 form.-decode :: forall i o. (Foldable' i, Element i ~ Char, Applicative' o, Item o ~ Word8) => i -> o-decode input = g . fold' f (0, 0, -1, mempty) $ input where+-- | Decodes a 'Word8' output sequence from a 'Char' input sequence in Base91 form; the opposite of 'encode'.+decode :: forall i o. (Input i Char, Output o Word8) => i -> o+decode input = g . ofoldl' f (0, 0, -1, mempty) $ input where f :: (Int, Int, Int, o) -> Char -> (Int, Int, Int, o) f (queue, nbits, value, output) c =@@ -51,14 +74,14 @@ q = queue .|. (v `shiftL` nbits) n = nbits + (if (v .&. 8191) > 88 then 13 else 14) (queue', nbits', x, y) = if n - 8 > 7- then (q `shiftR` 16, n - 16, pure' $ toWord8 q, pure' $ toWord8 $ q `shiftR` 8)- else (q `shiftR` 8, n - 8, pure' $ toWord8 q, mempty)+ then (q `shiftR` 16, n - 16, opoint $ toWord8 q, opoint $ toWord8 $ q `shiftR` 8)+ else (q `shiftR` 8, n - 8, opoint $ toWord8 q, mempty) in (queue', nbits', -1, mconcat [output, x, y]) g :: (Int, Int, Int, o) -> o g (_, _, -1, output) = output g (queue, nbits, value, output) = mappend output x- where x = pure' $ toWord8 $ queue .|. (value `shiftL` nbits)+ where x = opoint $ toWord8 $ queue .|. (value `shiftL` nbits) toWord8 :: Int -> Word8 toWord8 = fromIntegral
− Codec/Binary/Base91/ByteString.hs
@@ -1,29 +0,0 @@--- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.--{-# LANGUAGE TypeFamilies #-}--module Codec.Binary.Base91.ByteString (decode, encode) where--import Codec.Binary.Base91.Control (Applicative' (..), Foldable' (..))-import Data.ByteString (ByteString)-import Data.Word (Word8)-import qualified Codec.Binary.Base91 as Base91-import qualified Data.ByteString as BS----- | Encodes a 'ByteString' to ['Char'] in Base91; the opposite of 'decode'.-encode ::ByteString -> [Char]-encode = Base91.encode---- | Decodes a 'ByteString' from ['Char'] in Base91; the opposite of 'encode'.-decode :: [Char] -> ByteString-decode = Base91.decode---instance Applicative' ByteString where- type Item ByteString = Word8- pure' = BS.singleton--instance Foldable' ByteString where- type Element ByteString = Word8- fold' = BS.foldl'
− Codec/Binary/Base91/ByteString/Lazy.hs
@@ -1,29 +0,0 @@--- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.--{-# LANGUAGE TypeFamilies #-}--module Codec.Binary.Base91.ByteString.Lazy (decode, encode) where--import Codec.Binary.Base91.Control (Applicative' (..), Foldable' (..))-import Data.ByteString.Lazy (ByteString)-import Data.Word (Word8)-import qualified Codec.Binary.Base91 as Base91-import qualified Data.ByteString.Lazy as BSL----- | Encodes a (lazy) 'ByteString' to ['Char'] in Base91; the opposite of 'decode'.-encode ::ByteString -> [Char]-encode = Base91.encode---- | Decodes a (lazy) 'ByteString' from ['Char'] in Base91; the opposite of 'encode'.-decode :: [Char] -> ByteString-decode = Base91.decode---instance Applicative' ByteString where- type Item ByteString = Word8- pure' = BSL.singleton--instance Foldable' ByteString where- type Element ByteString = Word8- fold' = BSL.foldl'
− Codec/Binary/Base91/Control.hs
@@ -1,29 +0,0 @@--- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.--{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}--module Codec.Binary.Base91.Control (Applicative' (..), Foldable' (..)) where--import Control.Applicative (Applicative, pure)-import Data.Foldable (Foldable, foldl')-import Data.Monoid (Monoid)---- A version of 'Applicative' compatible with monomorphic containers.-class (Monoid a) => Applicative' a where- type Item a :: *- pure' :: Item a -> a--instance (Applicative a, Monoid (a i)) => Applicative' (a i) where- type Item (a i) = i- pure' = pure---- A version of 'Foldable' compatible with monomorphic containers.-class Foldable' f where- type Element f :: *- fold' :: (x -> Element f -> x) -> x -> f -> x--instance (Foldable f) => Foldable' (f e) where- type Element (f e) = e- fold' = foldl'
− Codec/Binary/Base91/Efficient.hs
@@ -1,18 +0,0 @@--- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.--module Codec.Binary.Base91.Efficient (decode, encode) where--import Codec.Binary.Base91.ByteString hiding (decode, encode)-import Codec.Binary.Base91.Text hiding (decode, encode)-import Data.ByteString (ByteString)-import Data.Text (Text)-import qualified Codec.Binary.Base91 as Base91----- | Encodes 'ByteString' to 'Text' in Base91; the opposite of 'decode'.-encode :: ByteString -> Text-encode = Base91.encode---- | Decodes 'ByteString' from 'Text' in Base91; the opposite of 'encode'.-decode :: Text -> ByteString-decode = Base91.decode
− Codec/Binary/Base91/Efficient/Lazy.hs
@@ -1,18 +0,0 @@--- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.--module Codec.Binary.Base91.Efficient.Lazy (decode, encode) where--import Codec.Binary.Base91.ByteString.Lazy hiding (decode, encode)-import Codec.Binary.Base91.Text.Lazy hiding (decode, encode)-import Data.ByteString.Lazy (ByteString)-import Data.Text.Lazy (Text)-import qualified Codec.Binary.Base91 as Base91----- | Encodes 'ByteString' to 'Text' in Base91; the opposite of 'decode'.-encode :: ByteString -> Text-encode = Base91.encode---- | Decodes 'ByteString' from 'Text' in Base91; the opposite of 'encode'.-decode :: Text -> ByteString-decode = Base91.decode
− Codec/Binary/Base91/String.hs
@@ -1,15 +0,0 @@--- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.--module Codec.Binary.Base91.String (decode, encode) where--import Data.Word (Word8)-import qualified Codec.Binary.Base91 as Base91----- | Encodes ['Word8'] to a 'String' in Base91; the opposite of 'decode'.-encode :: [Word8] -> String-encode = Base91.encode---- | Decodes ['Word8'] from a 'String' in Base91; the opposite of 'encode'.-decode :: String -> [Word8]-decode = Base91.decode
− Codec/Binary/Base91/Text.hs
@@ -1,29 +0,0 @@--- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.--{-# LANGUAGE TypeFamilies #-}--module Codec.Binary.Base91.Text (decode, encode) where--import Codec.Binary.Base91.Control (Applicative' (..), Foldable' (..))-import Data.Text (Text)-import Data.Word (Word8)-import qualified Codec.Binary.Base91 as Base91-import qualified Data.Text as T----- | Encodes ['Word8'] to 'Text' in Base91; the opposite of 'decode'.-encode :: [Word8] -> Text-encode = Base91.encode---- | Decodes ['Word8'] from 'Text' in Base91; the opposite of 'encode'.-decode :: Text -> [Word8]-decode = Base91.decode---instance Applicative' Text where- type Item (Text) = Char- pure' = T.singleton--instance Foldable' Text where- type Element (Text) = Char- fold' = T.foldl'
− Codec/Binary/Base91/Text/Lazy.hs
@@ -1,29 +0,0 @@--- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.--{-# LANGUAGE TypeFamilies #-}--module Codec.Binary.Base91.Text.Lazy (decode, encode) where--import Codec.Binary.Base91.Control (Applicative' (..), Foldable' (..))-import Data.Text.Lazy (Text)-import Data.Word (Word8)-import qualified Codec.Binary.Base91 as Base91-import qualified Data.Text.Lazy as TL----- | Encodes ['Word8'] to (lazy) 'Text' in Base91; the opposite of 'decode'.-encode :: [Word8] -> Text-encode = Base91.encode---- | Decodes ['Word8'] from (lazy) 'Text' in Base91; the opposite of 'encode'.-decode :: Text -> [Word8]-decode = Base91.decode---instance Applicative' Text where- type Item (Text) = Char- pure' = TL.singleton--instance Foldable' Text where- type Element (Text) = Char- fold' = TL.foldl'
Main.hs view
@@ -2,11 +2,12 @@ module Main (main) where -import Codec.Binary.Base91.Efficient as Base91-import Data.ByteString as BS-import Data.Text.IO as T import System.Environment (getArgs, getProgName) +import qualified Codec.Binary.Base91 as Base91+import qualified Data.ByteString as BS+import qualified Data.Text.IO as T+ main :: IO () main = getProgName >>= \name -> getArgs >>= \args -> case name:args of "b91enc":[] -> encode@@ -18,5 +19,5 @@ _ -> error "missing or invalid arguments" where- encode = BS.getContents >>= T.putStrLn . Base91.encode- decode = T.getContents >>= BS.putStr . Base91.decode+ encode = BS.getContents >>= T.putStrLn . Base91.encode+ decode = T.getContents >>= BS.putStr . Base91.decode
Test.hs view
@@ -1,17 +1,14 @@ -- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more. -import qualified Codec.Binary.Base91.ByteString as BS' (decode, encode)-import qualified Codec.Binary.Base91.ByteString.Lazy as BSL' (decode, encode)-import qualified Codec.Binary.Base91.Efficient as E' (decode, encode)-import qualified Codec.Binary.Base91.Efficient.Lazy as EL' (decode, encode)-import qualified Codec.Binary.Base91.String as S' (decode, encode)-import qualified Codec.Binary.Base91.Text as T' (decode, encode)-import qualified Codec.Binary.Base91.Text.Lazy as TL' (decode, encode)+{-# LANGUAGE TypeFamilies #-}++import Codec.Binary.Base91 (decode, encode)+import Data.Word (Word8)+import Test.QuickCheck (quickCheck) import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BSL import qualified Data.Text as T import qualified Data.Text.Lazy as TL-import Test.QuickCheck main :: IO () main = do@@ -20,8 +17,8 @@ testByteStringLazy testText testTextLazy- testEfficient- testEfficientLazy+ testByteString_Text+ testByteStringLazy_TextLazy where -- Note that the reverse identities, e.g. encode (decode cs) == cs, aren't true because not every@@ -30,58 +27,67 @@ testString = do quickCheck $ prop_identity- quickCheck $ example ([], [])+ quickCheck $ example empty quickCheck $ example helloWorld where- prop_identity ws = S'.decode (S'.encode ws) == ws- example (ws, cs) = S'.encode ws == cs && S'.decode cs == ws+ prop_identity :: [Word8] -> Bool+ prop_identity ws = decode (encode ws :: [Char]) == ws+ example (ws, cs) = (encode ws :: [Char]) == cs && decode cs == ws testByteString = do quickCheck $ prop_identity- quickCheck $ example ([], [])+ quickCheck $ example empty quickCheck $ example helloWorld where- prop_identity ws = BS'.decode (BS'.encode bs) == bs where bs = BS.pack ws- example (ws, cs) = BS'.encode bs == cs && BS'.decode cs == bs where bs = BS.pack ws+ prop_identity :: [Word8] -> Bool+ prop_identity ws = decode (encode bs :: [Char]) == bs where bs = BS.pack ws+ example (ws, cs) = (encode bs :: [Char]) == cs && decode cs == bs where bs = BS.pack ws testByteStringLazy = do quickCheck $ prop_identity- quickCheck $ example ([], [])+ quickCheck $ example empty quickCheck $ example helloWorld where- prop_identity ws = BSL'.decode (BSL'.encode bs) == bs where bs = BSL.pack ws- example (ws, cs) = BSL'.encode bs == cs && BSL'.decode cs == bs where bs = BSL.pack ws+ prop_identity :: [Word8] -> Bool+ prop_identity ws = decode (encode bs :: [Char]) == bs where bs = BSL.pack ws+ example (ws, cs) = (encode bs :: [Char]) == cs && decode cs == bs where bs = BSL.pack ws testText = do quickCheck $ prop_identity- quickCheck $ example ([], [])+ quickCheck $ example empty quickCheck $ example helloWorld where- prop_identity ws = T'.decode (T'.encode ws) == ws- example (ws, cs) = T'.encode ws == t && T'.decode t == ws where t = T.pack cs+ prop_identity :: [Word8] -> Bool+ prop_identity ws = decode (encode ws :: T.Text) == ws+ example (ws, cs) = (encode ws :: T.Text) == t && decode t == ws where t = T.pack cs testTextLazy = do quickCheck $ prop_identity- quickCheck $ example ([], [])+ quickCheck $ example empty quickCheck $ example helloWorld where- prop_identity ws = TL'.decode (TL'.encode ws) == ws- example (ws, cs) = TL'.encode ws == t && TL'.decode t == ws where t = TL.pack cs+ prop_identity :: [Word8] -> Bool+ prop_identity ws = decode (encode ws :: TL.Text) == ws+ example (ws, cs) = (encode ws :: TL.Text) == t && decode t == ws where t = TL.pack cs - testEfficient = do+ testByteString_Text = do quickCheck $ prop_identity- quickCheck $ example ([], [])+ quickCheck $ example empty quickCheck $ example helloWorld where- prop_identity ws = E'.decode (E'.encode bs) == bs where bs = BS.pack ws- example (ws, cs) = E'.encode bs == t && E'.decode t == bs where (bs, t) = (BS.pack ws, T.pack cs)+ prop_identity :: [Word8] -> Bool+ prop_identity ws = decode (encode bs :: T.Text) == bs where bs = BS.pack ws+ example (ws, cs) = (encode bs :: T.Text) == t && decode t == bs where (bs, t) = (BS.pack ws, T.pack cs) - testEfficientLazy = do+ testByteStringLazy_TextLazy = do quickCheck $ prop_identity- quickCheck $ example ([], [])+ quickCheck $ example empty quickCheck $ example helloWorld where- prop_identity ws = EL'.decode (EL'.encode bs) == bs where bs = BSL.pack ws- example (ws, cs) = EL'.encode bs == t && EL'.decode t == bs where (bs, t) = (BSL.pack ws, TL.pack cs)+ prop_identity :: [Word8] -> Bool+ prop_identity ws = decode (encode bs :: TL.Text) == bs where bs = BSL.pack ws+ example (ws, cs) = (encode bs :: TL.Text) == t && decode t == bs where (bs, t) = (BSL.pack ws, TL.pack cs) + empty, helloWorld :: ([Word8], [Char])+ empty = ([], "") helloWorld = ([72,101,108,108,111,44,32,119,111,114,108,100,33,10], ">OwJh>}A\"=r@@Y?FF") -- "Hello, World!\n"
base91.cabal view
@@ -1,51 +1,30 @@ Name: base91-Version: 1.1.0+Version: 2.0.0 Author: Alvaro J. Genial Maintainer: ajg Homepage: https://github.com/ajg/base91 Synopsis: A Base91 Encoder & Decoder Description: An implementation of Base91 encoding & decoding of arbitrary bytes (octets)- to/from characters (all in the ASCII printable range); it includes support- for plain Strings, as well as optional support for ByteString and/or Text and- their lazy variants; see the Flags section for details.+ to/from characters (all in the ASCII printable range) License: MIT License-File: LICENSE.md Category: Codec Build-Type: Simple Cabal-Version: >= 1.8 -Flag ByteString- Description: Enable support for Data.ByteString and Data.ByteString.Lazy.- Default: True--Flag Text- Description: Enable support for Data.Text and Data.Text.Lazy.- Default: True- Library- Build-Depends: base >= 4 && < 5- Exposed-Modules: Codec.Binary.Base91, Codec.Binary.Base91.Control, Codec.Binary.Base91.String-- if flag(ByteString)- Build-Depends: bytestring- Exposed-Modules: Codec.Binary.Base91.ByteString, Codec.Binary.Base91.ByteString.Lazy-- if flag(Text)- Build-Depends: text- Exposed-Modules: Codec.Binary.Base91.Text, Codec.Binary.Base91.Text.Lazy-- if flag(ByteString) && flag(Text)- Exposed-Modules: Codec.Binary.Base91.Efficient, Codec.Binary.Base91.Efficient.Lazy+ Build-Depends: base >= 4 && < 5, mono-traversable+ Exposed-Modules: Codec.Binary.Base91 Executable base91 Main-is: Main.hs- Build-Depends: base, base91, bytestring, text+ Build-Depends: base, base91, bytestring, mono-traversable, text Test-Suite tests Hs-Source-Dirs: . Main-Is: Test.hs Type: exitcode-stdio-1.0- Build-Depends: base, base91, bytestring, text, QuickCheck+ Build-Depends: base, base91, bytestring, mono-traversable, text, QuickCheck Source-Repository head type: git