text-conversions 0.2.0 → 0.3.0
raw patch · 5 files changed
+81/−7 lines, 5 filesdep +base16-bytestringdep +base64-bytestring
Dependencies added: base16-bytestring, base64-bytestring
Files
- README.md +3/−3
- package.yaml +3/−1
- src/Data/Text/Conversions.hs +46/−2
- test/Data/Text/ConversionsSpec.hs +26/−0
- text-conversions.cabal +3/−1
README.md view
@@ -2,7 +2,7 @@ This is a small library to ease the pain when converting between the many different string types in Haskell. Unlike some other libraries that attempt to solve the same problem, text-conversions is: - - **Safe.** This library treats binary data (aka `ByteString`) like binary data, and it does not assume a particular encoding, nor does it ever throw exceptions when failing to decode. It does, however, provide failable conversions between binary data and textual data through the same exact interface as conversions between purely textual data.+ - **Safe.** This library treats binary data (aka `ByteString`) like binary data, and it does not assume a particular encoding, nor does it ever throw exceptions when failing to decode. It does, however, provide failable conversions between binary data and textual data. - **Extensible.** It’s easy to add or derive your own instances of the typeclasses to use your own types through the same interface. @@ -16,9 +16,9 @@ And here’s an example of converting from UTF-8 encoded binary data to a textual format: ```haskell-> convertText (UTF8 ("hello" :: ByteString)) :: Maybe Text+> decodeConvertText (UTF8 ("hello" :: ByteString)) :: Maybe Text Just "hello"-> convertText (UTF8 ("\xc3\x28" :: ByteString)) :: Maybe Text+> decodeConvertText (UTF8 ("\xc3\x28" :: ByteString)) :: Maybe Text Nothing ```
package.yaml view
@@ -1,5 +1,5 @@ name: text-conversions-version: '0.2.0'+version: '0.3.0' category: Data synopsis: Safe conversions between textual types description: Safe conversions between textual types@@ -27,6 +27,8 @@ dependencies: - base >= 4.7 && < 5 - bytestring+ - base16-bytestring+ - base64-bytestring - errors - text
src/Data/Text/Conversions.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE Safe #-} {-# LANGUAGE DeriveFunctor #-} {-|@@ -37,7 +36,9 @@ Nothing -} module Data.Text.Conversions- ( DecodeText(..)+ ( Base16(..)+ , Base64(..)+ , DecodeText(..) , FromText(..) , ToText(..) , UTF8(..)@@ -55,6 +56,11 @@ import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL +import qualified Data.ByteString.Base16 as Base16+import qualified Data.ByteString.Base16.Lazy as Base16L+import qualified Data.ByteString.Base64 as Base64+import qualified Data.ByteString.Base64.Lazy as Base64L+ {-| Simple wrapper type that is used to select a desired encoding when encoding or decoding text from binary data, such as 'Data.ByteString.ByteString's.@@ -63,6 +69,20 @@ deriving (Eq, Show, Functor) {-|+ Wrapper type used to select a base 16 encoding when encoding or decoding+ binary data. Safe because base 16 encoding will always produce ASCII output.+-}+newtype Base16 a = Base16 { unBase16 :: a }+ deriving (Eq, Show, Functor)++{-|+ Wrapper type used to select a base 64 encoding when encoding or decoding+ binary data. Safe because base 64 encoding will always produce ASCII output.+-}+newtype Base64 a = Base64 { unBase64 :: a }+ deriving (Eq, Show, Functor)++{-| A simple typeclass that handles converting arbitrary datatypes to 'Data.Text.Text' when the operation cannot fail. If you have a type that satisfies that requirement, implement this typeclass, but if the operation can@@ -124,3 +144,27 @@ instance FromText (UTF8 B.ByteString) where fromText = UTF8 . T.encodeUtf8 instance DecodeText Maybe (UTF8 BL.ByteString) where decodeText = hush . fmap TL.toStrict . TL.decodeUtf8' . unUTF8 instance FromText (UTF8 BL.ByteString) where fromText = UTF8 . TL.encodeUtf8 . TL.fromStrict++instance ToText (Base16 B.ByteString) where+ toText = T.decodeUtf8 . Base16.encode . unBase16+instance FromText (Maybe (Base16 B.ByteString)) where+ fromText txt = case Base16.decode (T.encodeUtf8 txt) of+ (bs, "") -> Just $ Base16 bs+ (_, _) -> Nothing++instance ToText (Base64 B.ByteString) where+ toText = T.decodeUtf8 . Base64.encode . unBase64+instance FromText (Maybe (Base64 B.ByteString)) where+ fromText = fmap Base64 . hush . Base64.decode . T.encodeUtf8++instance ToText (Base16 BL.ByteString) where+ toText = TL.toStrict . TL.decodeUtf8 . Base16L.encode . unBase16+instance FromText (Maybe (Base16 BL.ByteString)) where+ fromText txt = case Base16L.decode (TL.encodeUtf8 $ TL.fromStrict txt) of+ (bs, "") -> Just $ Base16 bs+ (_, _) -> Nothing++instance ToText (Base64 BL.ByteString) where+ toText = TL.toStrict . TL.decodeUtf8 . Base64L.encode . unBase64+instance FromText (Maybe (Base64 BL.ByteString)) where+ fromText = fmap Base64 . hush . Base64L.decode . TL.encodeUtf8 . TL.fromStrict
test/Data/Text/ConversionsSpec.hs view
@@ -49,6 +49,32 @@ convertText ("hello" :: T.Text) `shouldBe` UTF8 ("hello" :: B.ByteString) convertText ("hello" :: T.Text) `shouldBe` UTF8 ("hello" :: BL.ByteString) + describe "Base16" $ do+ it "encodes bytestrings as base 16 encoded text" $ do+ convertText (Base16 ("hello" :: B.ByteString)) `shouldBe` ("68656c6c6f" :: T.Text)+ convertText (Base16 ("hello" :: BL.ByteString)) `shouldBe` ("68656c6c6f" :: T.Text)++ it "decodes properly encoded base 16 text as bytestrings" $ do+ convertText ("68656c6c6f" :: T.Text) `shouldBe` Just (Base16 ("hello" :: B.ByteString))+ convertText ("68656c6c6f" :: T.Text) `shouldBe` Just (Base16 ("hello" :: BL.ByteString))++ it "fails to decode improperly encoded base 16 text as bytestrings" $ do+ convertText ("not base 16" :: T.Text) `shouldBe` (Nothing :: Maybe (Base16 B.ByteString))+ convertText ("not base 16" :: T.Text) `shouldBe` (Nothing :: Maybe (Base16 BL.ByteString))++ describe "Base64" $ do+ it "encodes bytestrings as base 64 encoded text" $ do+ convertText (Base64 ("hello" :: B.ByteString)) `shouldBe` ("aGVsbG8=" :: T.Text)+ convertText (Base64 ("hello" :: BL.ByteString)) `shouldBe` ("aGVsbG8=" :: T.Text)++ it "decodes properly encoded base 64 text as bytestrings" $ do+ convertText ("aGVsbG8=" :: T.Text) `shouldBe` Just (Base64 ("hello" :: B.ByteString))+ convertText ("aGVsbG8=" :: T.Text) `shouldBe` Just (Base64 ("hello" :: BL.ByteString))++ it "fails to decode improperly encoded base 64 text as bytestrings" $ do+ convertText ("not base 16" :: T.Text) `shouldBe` (Nothing :: Maybe (Base64 B.ByteString))+ convertText ("not base 16" :: T.Text) `shouldBe` (Nothing :: Maybe (Base64 BL.ByteString))+ describe "decodeConvertText" $ do it "can convert between things in functors with a DecodeText instance" $ decodeConvertText FailableString `shouldBe` Just ("failable" :: TL.Text)
text-conversions.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack name: text-conversions-version: 0.2.0+version: 0.3.0 synopsis: Safe conversions between textual types description: Safe conversions between textual types category: Data@@ -35,6 +35,8 @@ build-depends: base >= 4.7 && < 5 , bytestring+ , base16-bytestring+ , base64-bytestring , errors , text exposed-modules: