packages feed

typed-encoding 0.5.0.0 → 0.5.1.0

raw patch · 12 files changed

+159/−14 lines, 12 files

Files

ChangeLog.md view
@@ -7,6 +7,11 @@ - `Data.TypedEncoding.Common.Class.IsStringR` expected to be be changed / replaced - More module renaming to separate internal implementation code and code targeting examples - (post 0.5) "enc-B64" will be moved to a different package (more distant goal)+- (intended as private) @implVerifyR@ will be removed from Data.TypedEncoding.Instances.Restriction.UTF8++## 0.5.1.0+- "r-B64" added+- @implVerifyR@ convenience function added to 'Data.TypedEncoding.Instances.Support.Encode'  ## 0.5.0 
README.md view
@@ -72,6 +72,12 @@  Please see `Examples.TypedEncoding` it the module list. + ++## Hackage++https://hackage.haskell.org/package/typed-encoding+ ## Other encoding packages  My approach will be to write specific encodings (e.g. _HTTP_) or wrap encodings from other packages using separate "bridge" projects.
src/Data/TypedEncoding/Common/Class.hs view
@@ -55,7 +55,7 @@  -- | Flatten is more permissive 'IsSuperset' -- @--- instance FlattenAs "r-ASCII" "enc-B64" where -- OK+-- instance FlattenAs "r-ASCII" "enc-B64" where  -- @ --  -- Now encoded data has form @Enc '["r-ASCII"] c str@ 
src/Data/TypedEncoding/Common/Class/Superset.hs view
@@ -64,7 +64,10 @@ -- -- @since 0.2.2.0 type family IsSuperset (y :: Symbol) (x :: Symbol) :: Bool where+    IsSuperset "r-B64" "r-B64" = 'True+    IsSuperset "r-ASCII" "r-B64" = 'True     IsSuperset "r-ASCII" "r-ASCII" = 'True+    IsSuperset "r-UTF8" "r-B64" = 'True     IsSuperset "r-UTF8"  "r-ASCII" = 'True     IsSuperset "r-UTF8"  "r-UTF8" = 'True     IsSuperset "r-CHAR8" "r-ASCII" = 'True  -- "r-CHAR8" is phantom, no explicit instances so it does not need reflexive case
src/Data/TypedEncoding/Common/Types/Enc.hs view
@@ -127,7 +127,7 @@ -- Encoding Identity "enc-B64" "enc-B64" () ByteString -- @ ----- Represents a /Byte 64/ encoder that can operate on any stack of previous encodings.+-- Represents a /Base 64/ encoder that can operate on any stack of previous encodings. -- (encoding name and algorithm name are "enc-B64", there is no   -- additional configuration @()@ needed and it runs in the @Identity@ Functor. --
src/Data/TypedEncoding/Instances/Enc/Base64.hs view
@@ -21,6 +21,7 @@  import qualified Data.ByteString.Base64 as B64 import qualified Data.ByteString.Base64.Lazy as BL64+import           Data.TypedEncoding.Instances.Restriction.Base64 ()   @@ -51,6 +52,18 @@ acceptLenientL :: Enc ("enc-B64-len" ': ys) c BL.ByteString -> Enc ("enc-B64" ': ys) c BL.ByteString  acceptLenientL = withUnsafeCoerce (BL64.encode . BL64.decodeLenient) +-- |+-- Validated "r-B64" is guaranteed to decode.  +-- This would not be safe for Text+asEncodingB :: Enc '["r-B64"] c B.ByteString ->  Enc '["enc-B64"] c B.ByteString +asEncodingB = withUnsafeCoerce id++-- |+-- Validated "r-B64" is guaranteed to decode.  +-- This would not be safe for Text+asEncodingBL :: Enc '["r-B64"] c BL.ByteString ->  Enc '["enc-B64"] c BL.ByteString +asEncodingBL = withUnsafeCoerce id+ -- | allow to treat B64 encodings as ASCII forgetting about B64 encoding --  --@@ -66,6 +79,10 @@ instance FlattenAs "r-ASCII" "enc-B64" where  -- |+-- @since 0.5.1.0 +instance FlattenAs "r-B64" "enc-B64" where++-- | -- This is not precise, actually /Base 64/ uses a subset of ASCII -- and that would require a new definition @"r-B64"@. --@@ -80,13 +97,13 @@ -- -- @since 0.3.0.0 instance EncodingSuperset "enc-B64" where-    type EncSuperset "enc-B64" = "r-ASCII"+    type EncSuperset "enc-B64" = "r-B64"  -- | -- >>> tstChar8Encodable @ '["enc-B64-len", "enc-B64"] -- "I am CHAR8 encodable" instance EncodingSuperset "enc-B64-len" where-    type EncSuperset "enc-B64-len" = "r-ASCII"+    type EncSuperset "enc-B64-len" = "r-B64"  -- * Encoders 
+ src/Data/TypedEncoding/Instances/Restriction/Base64.hs view
@@ -0,0 +1,99 @@+{-# LANGUAGE DataKinds #-}+--{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+--{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE PartialTypeSignatures #-}+--{-# LANGUAGE TypeApplications #-}++-- | 'r-B64' is restricted to values that are valid Base64 encodings of some data.+-- For example, @Enc '["r-B64"] () T.Text@ can contain encoded binary image.+--+-- "enc-B64" can be converted to "r-B64" using @flattenAs@ defined in+-- 'Data.TypedEncoding.Instances.Enc.Base64'.     +-- However, there is no, and there should be no conversion general conversion from "r-B64" back to "enc-B64":+-- @Enc '["r-B64"] () T.Text@ is not B64 encoded text, it is B64 encoded something.+--+-- @since 0.5.1.0+module Data.TypedEncoding.Instances.Restriction.Base64 where++import           Data.TypedEncoding.Instances.Support+++import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BL+import qualified Data.Text.Encoding as TE +import qualified Data.Text.Lazy.Encoding as TEL +import qualified Data.ByteString.Base64 as B64+import qualified Data.ByteString.Base64.Lazy as BL64+import qualified Data.ByteString.Char8 as B8+import qualified Data.TypedEncoding.Instances.Restriction.ASCII as RAscii++-- $setup+-- >>> :set -XScopedTypeVariables -XKindSignatures -XMultiParamTypeClasses -XDataKinds -XPolyKinds -XPartialTypeSignatures -XFlexibleInstances -XTypeApplications++++instance Encode (Either EncodeEx) "r-B64" "r-B64" c B.ByteString where+    encoding = encRB64B+  +instance Encode (Either EncodeEx) "r-B64" "r-B64" c BL.ByteString where+    encoding = encRB64BL+  ++instance Encode (Either EncodeEx) "r-B64" "r-B64" c T.Text where+    encoding = encRB64T+  +instance Encode (Either EncodeEx) "r-B64" "r-B64" c TL.Text where+    encoding = encRB64TL++instance Encode (Either EncodeEx) "r-B64" "r-B64" c String where+    encoding = encRB64S++-- using lazy decoding to detect errors seems to be the fastest option that is not super hard to code+++encRB64B :: Encoding (Either EncodeEx) "r-B64" "r-B64" c B.ByteString+encRB64B = _implEncodingEx (implVerifyR (B64.decode)) ++encRB64BL :: Encoding (Either EncodeEx) "r-B64" "r-B64" c BL.ByteString+encRB64BL = _implEncodingEx (implVerifyR (BL64.decode)) ++-- | Converts text to bytestring using UTF8 decoding and then verify encoding in ByteString+-- This is safe without verifying ASCII, any non-ASCII text will still convert to ByteString+-- but will fail B64.decode (TODO tests would be nice)+encRB64T :: Encoding (Either EncodeEx) "r-B64" "r-B64" c T.Text+encRB64T = _implEncodingEx (implVerifyR (B64.decode . TE.encodeUtf8)) ++encRB64TL :: Encoding (Either EncodeEx) "r-B64" "r-B64" c TL.Text+encRB64TL = _implEncodingEx (implVerifyR (BL64.decode . TEL.encodeUtf8)) ++encRB64S :: Encoding (Either EncodeEx) "r-B64" "r-B64" c String+encRB64S = _implEncodingEx (implVerifyR (fmap (B64.decode . B8.pack) . either (Left . show) Right . RAscii.encImpl)) ++-- -- * Decoding++instance (Applicative f) => Decode f "r-B64" "r-B64" c str where+    decoding = decAnyR++instance (RecreateErr f, Applicative f) =>  Validate f "r-B64" "r-B64" c B.ByteString  where+    validation = validR encRB64B++instance (RecreateErr f, Applicative f) =>  Validate f "r-B64" "r-B64" c BL.ByteString  where+    validation = validR encRB64BL++instance (RecreateErr f, Applicative f) =>  Validate f "r-B64" "r-B64" c T.Text  where+    validation = validR encRB64T++instance (RecreateErr f, Applicative f) =>  Validate f "r-B64" "r-B64" c TL.Text  where+    validation = validR encRB64TL++instance (RecreateErr f, Applicative f) =>  Validate f "r-B64" "r-B64" c String  where+    validation = validR encRB64S+
src/Data/TypedEncoding/Instances/Restriction/UTF8.hs view
@@ -16,7 +16,11 @@ -- conversion to @Text@ to work. -- -- @since 0.1.0.0-module Data.TypedEncoding.Instances.Restriction.UTF8 where+module Data.TypedEncoding.Instances.Restriction.UTF8 (+     module Data.TypedEncoding.Instances.Restriction.UTF8+     -- * reexported for backward compatibility, will be removed in the future+     , implVerifyR +   ) where  import           Data.TypedEncoding.Instances.Support @@ -109,9 +113,3 @@ verEncoding bs (Left _) = isLeft . TE.decodeUtf8' $ bs verEncoding bs (Right _) = isRight . TE.decodeUtf8' $ bs --- | private implementation helper-implVerifyR :: (a -> Either err b) -> a -> Either err a-implVerifyR fn a = -     case fn a of -         Left err -> Left err-         Right _ -> Right a
src/Data/TypedEncoding/Instances/Support/Encode.hs view
@@ -84,3 +84,10 @@         p = Proxy :: Proxy nm  +-- |+-- @since 0.5.1.0+implVerifyR :: (a -> Either err b) -> a -> Either err a+implVerifyR fn a = +     case fn a of +         Left err -> Left err+         Right _ -> Right a
src/Examples/TypedEncoding/Conversions.hs view
@@ -65,6 +65,7 @@  import           Data.TypedEncoding import           Data.TypedEncoding.Instances.Enc.Base64 () +import           Data.TypedEncoding.Instances.Restriction.Base64 ()  import           Data.TypedEncoding.Instances.Restriction.ASCII () import           Data.TypedEncoding.Instances.Restriction.UTF8 () import           Data.TypedEncoding.Instances.Restriction.D76 ()@@ -278,6 +279,14 @@ --  +notTextB64AsTxt :: Enc '["r-B64"] () T.Text+notTextB64AsTxt =  EncTe.decodeUtf8 $ flattenAs $ notTextB+-- ^ /Base64/ encoding of a non-text binary data can still be converted to Text format+--  @Enc '["r-B64"] () T.Text@ signifies that the value is B64 encoding but it cannot be decoded to a Text. +++-- tst = encodeAll . toEncoding () $ "" :: Enc '["enc-B64"] () B.ByteString+-- tst2 = EncTe.decodeUtf8 $ flattenAs $ tst :: Enc '["r-B64"] () T.Text  -- * Lenient recovery 
test/Test/SupersetSpec.hs view
@@ -37,6 +37,6 @@         describe "String based" $              it "r-UNICODE.D76 > r-ASCII" $ property $ propSuperset_ @"r-UNICODE.D76" @"r-ASCII" @String encoding encoding         describe "EncodingSuperset test" $-            it "enc-B64 < r-ASCII" $ property $ propEncodesInto_ @"enc-B64" @"r-ASCII" @B.ByteString encoding encoding+            it "enc-B64 < r-ASCII" $ property $ propEncodesInto_ @"enc-B64" @"r-B64" @B.ByteString encoding encoding runSpec :: IO () runSpec = hspec spec   
typed-encoding.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 14b481e19f8b924154bf83e2d8d55492f1f8259385026d9dc0c745a2924621fa+-- hash: df1ee6c51c573402710616f718103b1f8d79bc8811d5aa416e628c8f30ad927f  name:           typed-encoding-version:        0.5.0.0+version:        0.5.1.0 synopsis:       Type safe string transformations description:    See README.md in the project github repository. category:       Data, Text@@ -66,6 +66,7 @@       Data.TypedEncoding.Instances.Enc.Base64       Data.TypedEncoding.Instances.Enc.Warn.Base64       Data.TypedEncoding.Instances.Restriction.ASCII+      Data.TypedEncoding.Instances.Restriction.Base64       Data.TypedEncoding.Instances.Restriction.BoundedAlphaNums       Data.TypedEncoding.Instances.Restriction.ByteRep       Data.TypedEncoding.Instances.Restriction.CHAR8