typed-encoding 0.5.1.0 → 0.5.2.0
raw patch · 18 files changed
+251/−73 lines, 18 filesdep ~base64-bytestring
Dependency ranges changed: base64-bytestring
Files
- ChangeLog.md +9/−5
- README.md +23/−17
- src/Data/TypedEncoding.hs +11/−3
- src/Data/TypedEncoding/Common/Class.hs +1/−1
- src/Data/TypedEncoding/Common/Class/Encode.hs +20/−0
- src/Data/TypedEncoding/Common/Class/Superset.hs +15/−10
- src/Data/TypedEncoding/Common/Types/Enc.hs +69/−11
- src/Data/TypedEncoding/Conv/Text.hs +14/−0
- src/Data/TypedEncoding/Conv/Text/Encoding.hs +26/−1
- src/Data/TypedEncoding/Conv/Text/Lazy.hs +14/−0
- src/Data/TypedEncoding/Conv/Text/Lazy/Encoding.hs +14/−0
- src/Data/TypedEncoding/Instances/Enc/Base64.hs +15/−8
- src/Data/TypedEncoding/Instances/Restriction/ASCII.hs +2/−2
- src/Data/TypedEncoding/Instances/Restriction/UTF8.hs +2/−2
- src/Examples/TypedEncoding/Conversions.hs +4/−6
- src/Examples/TypedEncoding/Overview.hs +5/−0
- src/Examples/TypedEncoding/ToEncString.hs +2/−2
- typed-encoding.cabal +5/−5
ChangeLog.md view
@@ -2,14 +2,18 @@ ## Anticipated future breaking changes -- `Data.TypedEncoding.Instances.Do.Sample` will be moved to `Examples`-- `HasA` Typeclass will be moved to `Examples` - `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+- (post 0.5) "enc-B64" could be moved to a different package (more distant goal) +## 0.5.2.0++- Fixed up IsSuperset type family improving transitivity+- added `_mkEncoding1` `runEncoding1'` functions that show equivalence of `Encoding` to one level encoding+- added convenience one level encoding conversion functions+- base64-bytestring deps relaxed+ ## 0.5.1.0+ - "r-B64" added - @implVerifyR@ convenience function added to 'Data.TypedEncoding.Instances.Support.Encode'
README.md view
@@ -30,6 +30,9 @@ - converting types to encoded strings - typesafe conversion of encoded strings to types +Partial and dangerous things like `decodeUtf8` are no longer dangerous, +`ByteString` `Text` conversions become fully reversible. Life is good!+ ... but this approach seems to be a bit more... ```Haskell@@ -45,19 +48,30 @@ - used with parameters - applied or undone partially (if encoding is reversible) -One of more interesting uses of this library are encoding restrictions. -(Arbitrary) bounded alpha-numeric (`"r-ban"`) restrictions -and a simple annotation Boolean algebra are both provided.+One of more interesting uses of this library are encoding restrictions included in this library. +Example are (arbitrary) bounded alpha-numeric (`"r-ban"`) restrictions. ```Haskell-phone :: Enc '["r-ban:999-999-9999"] () T.Text-phone = ...+-- allow only properly formatted phone numbers --- simple boolean algebra:-phone' :: Enc '["boolOr:(r-ban:999-999-9999)(r-ban:(999) 999-9999)"] () T.Text-phone' = ...+type PhoneSymbol = "r-ban:999-999-9999"+phone :: Enc '[PhoneSymbol] () T.Text+phone = ... ``` +The author often uses _typed_encoding_ with _Servant_ (`HttpApiData` instances are not included), e.g.:++```Haskell+type LookupByPhone = + "customer"+ :> "byphone"+ :> Capture "phone" (Enc '[PhoneSymbol] () T.Text)+ :> Get '[JSON] ([Customer])+```++or to get type safety over text document using Unix vs Windows line breaks!++ ## Goals and limitations The main goal is to provide improved type safety for programs that use string encodings and @@ -72,12 +86,7 @@ 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.@@ -88,11 +97,8 @@ Bridge work: -- [typed-encoding-encoding](https://github.com/rpeszek/typed-encoding-encoding) bridges [encoding](https://github.com/dmwit/encoding) package--## News +- [typed-encoding-encoding](https://github.com/rpeszek/typed-encoding-encoding) bridges [encoding](https://github.com/dmwit/encoding) package -- v0.3 has numerous changes and improvements. ## Tested with
src/Data/TypedEncoding.hs view
@@ -63,8 +63,10 @@ -- -- Examples: @"r-UTF8"@, @"r-ASCII"@, upper alpha-numeric bound /r-ban/ restrictions like @"r-ban:999-999-9999"@ ----- == "do-" transformations (not provided in this library other than as /Examples/ "Examples.TypedEncoding.Instances.Do.Sample")+-- == "do-" transformations --+--(not provided in this library other than as /Examples/ "Examples.TypedEncoding.Instances.Do.Sample")+-- -- * /encoding/ applies transformation to the string (could be partial) -- * /decoding/ - typically none -- * /validation/ - typically none but, if present, verifies the payload has expected data (e.g. only uppercase chars for "do-UPPER")@@ -119,15 +121,17 @@ , toEncoding , fromEncoding , getPayload-+ -- * Untyped versions of @Enc@ , module Data.TypedEncoding.Common.Types.CheckedEnc -- * @Encoding@ and basic combinators , Encoding (..) , _mkEncoding+ , _mkEncoding1 , runEncoding' , _runEncoding + , runEncoding1' -- * List of encodings , Encodings (..)@@ -148,7 +152,11 @@ , propSafeValidatedDecoding' , _propSafeValidatedDecoding - -- * Classes+ -- * Encoding Classes+ , Encode (..)+ , EncodeAll (..)++ -- * Decoding, Validation and Other Classes , module Data.TypedEncoding.Common.Class -- * Combinators
src/Data/TypedEncoding/Common/Class.hs view
@@ -53,7 +53,7 @@ -- Other classes -- --- | Flatten is more permissive 'IsSuperset'+-- | Flatten is a more permissive 'IsSuperset' -- @ -- instance FlattenAs "r-ASCII" "enc-B64" where -- @
src/Data/TypedEncoding/Common/Class/Encode.hs view
@@ -20,8 +20,19 @@ import Data.TypedEncoding.Common.Types.Enc +-- $setup+-- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds -XAllowAmbiguousTypes+-- >>> import qualified Data.ByteString as B+-- >>> import Data.Functor.Identity+-- >>> import Data.TypedEncoding+-- >>> import Data.TypedEncoding.Instances.Enc.Base64 () -- | +-- Allows for polymorphic access to encoding, for example+--+-- >>> displ (runIdentity . _runEncoding encoding $ toEncoding () "Hello" :: Enc '["enc-B64"] () B.ByteString)+-- "Enc '[enc-B64] () (ByteString SGVsbG8=)"+-- -- Using 2 Symbol type variables (@nm@ and @alg@) creates what seems like redundant typing -- in statically defined instances such as @"r-ASCII"@, however it -- provides future flexibility to @@ -37,6 +48,15 @@ encoding :: Encoding f nm alg conf str -- |+-- Allows for polymorphic access to Encodings+-- +-- For example+--+-- >>> displ (runIdentity . _runEncodings encodings $ toEncoding () "Hello" :: (Enc '["enc-B64", "enc-B64"] () B.ByteString))+-- "Enc '[enc-B64,enc-B64] () (ByteString U0dWc2JHOD0=)"+--+-- You can also use convenience functions like @encodeAll@+-- -- @since 0.3.0.0 class EncodeAll f nms algs conf str where encodings :: Encodings f nms algs conf str
src/Data/TypedEncoding/Common/Class/Superset.hs view
@@ -62,22 +62,27 @@ -- Note, no IsSuperset "r-UNICODE.D76" "r-CHAR8" even though the numeric range of D76 includes all CHAR8 bytes. -- This is more /nominal/ decision that prevents certain unwanted conversions from being possible. --+-- This is not fully transitive to conserve compilation cost. -- @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-B64" "r-B64" = 'True -- "r-B64" is currently not expected to have any explicit superset logic 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- IsSuperset "r-CHAR8" "r-ByteRep" = 'True- IsSuperset "r-UNICODE.D76" "r-UNICODE.D76" = 'True - IsSuperset "r-UNICODE.D76" "r-ASCII" = 'True - IsSuperset "r-UNICODE.D76" x = Or (IsSuperset "r-CHAR8" x) (IsSupersetOpen "r-UNICODE.D76" x (TakeUntil x ":") (ToList x))+ IsSuperset "r-ASCII" "r-B64" = 'True+ IsSuperset "r-UNICODE.D76" "r-UNICODE.D76" = 'True -- guards what can go to Text + -- "r-UNICODE.D76" and "r-UTF8" should be considered equivalent+ -- currently there is no subset relationship between them+ -- IsSuperset "r-UNICODE.D76" "r-ASCII" = 'True -- redundant+ IsSuperset "r-UNICODE.D76" x = Or (IsSuperset "r-ASCII" x) (IsSupersetOpen "r-UNICODE.D76" x (TakeUntil x ":") (ToList x))+ IsSuperset "r-UTF8" "r-UTF8" = 'True + -- IsSuperset "r-UTF8" "r-ASCII" = 'True -- redundant+ IsSuperset "r-UTF8" x = Or (IsSuperset "r-ASCII" x) (IsSupersetOpen "r-UTF8" x (TakeUntil x ":") (ToList x)) + -- IsSuperset "r-CHAR8" "r-ASCII" = 'True -- redundant+ IsSuperset "r-CHAR8" "r-ByteRep" = 'True -- "r-CHAR8" is phantom root type defining type safe ByteString pack and unpack, it is not used directly, nor is a subset+ -- "r-ByteRep" is another encoding with special handling IsSuperset "r-CHAR8" x = Or (IsSuperset "r-ASCII" x) (IsSupersetOpen "r-CHAR8" x (TakeUntil x ":") (ToList x)) IsSuperset y x = IsSupersetOpen y x (TakeUntil x ":") (ToList x) + -- TODO introduce "r-NODEC" which does not decode
src/Data/TypedEncoding/Common/Types/Enc.hs view
@@ -32,7 +32,7 @@ -- >>> import Data.Functor.Identity -- >>> import Data.TypedEncoding -- >>> import Data.TypedEncoding.Instances.Enc.Base64 ()--- >>> import Data.TypedEncoding.Instances.Restriction.BoundedAlphaNums ()+-- >>> import Data.TypedEncoding.Instances.Restriction.BoundedAlphaNums (encFBan) -- | -- Contains encoded data annotated by @@ -84,7 +84,10 @@ getPayload :: Enc enc conf str -> str getPayload (UnsafeMkEnc _ _ str) = str - +-- |+-- @since 0.5.2.0+getContent :: Enc enc conf str -> (conf, str) +getContent (UnsafeMkEnc _ c str) = (c, str) -- | -- Wraps the encoding function.@@ -115,6 +118,13 @@ -- with definitions like @"r-ban"@ where @"r-ban:@" can be followed by arbitrary -- string literal. --+-- This existential definition is intended for clarity. /typed-encoding/ supports type level lists of encodings+-- and each encoding should not know what encodings have already been applied.+--+-- However, this construction is mostly equivalent to storing a simple one level encoding function +-- @Enc ('[]:: [Symbol]) conf str -> f (Enc '[nm] conf str)@ +-- (see '_mkEncoding1' and 'runEncoding1'' below). +-- -- Examples: -- -- @@@ -145,6 +155,8 @@ -- would make compilation much slower UnsafeMkEncoding :: Proxy nm -> (forall (xs :: [Symbol]) . Enc xs conf str -> f (Enc (nm ': xs) conf str)) -> Encoding f nm alg conf str ++ -- | Type safe smart constructor -- -- Adding the type family @(AlgNm nm)@ mapping to @Encoding@ constructor slows down the compilation. @@ -165,28 +177,55 @@ -- This particular function appears to not increase compilation time. -- -- @since 0.3.0.0-_mkEncoding :: forall f (nm :: Symbol) conf str . (forall (xs :: [Symbol]) . Enc xs conf str -> f (Enc (nm ': xs) conf str)) -> Encoding f nm (AlgNm nm) conf str+_mkEncoding :: forall f (nm :: Symbol) conf str . + (forall (xs :: [Symbol]) . Enc xs conf str -> f (Enc (nm ': xs) conf str)) -> Encoding f nm (AlgNm nm) conf str _mkEncoding = UnsafeMkEncoding Proxy -- |+-- Defines encoding by only specifying a simple one level encoding function. +-- This typically is not used in constructing encodings as there are more convenient combinators for doing this+-- (e.g. in "Data.TypedEncoding.Instances.Support").+-- It is here for completeness to show that the @Encoding@ definition is a bit overdone.+-- +-- @since 0.5.2.0+_mkEncoding1 :: forall f (nm :: Symbol) conf str . + Functor f => (Enc ('[]:: [Symbol]) conf str -> f (Enc '[nm] conf str)) -> Encoding f nm (AlgNm nm) conf str+_mkEncoding1 fn = UnsafeMkEncoding Proxy (fmap (mkenc Proxy . getContent) . fn . mkenc Proxy . getContent)+ where + mkenc p (c,s) = UnsafeMkEnc p c s+ +-- | -- @since 0.3.0.0 runEncoding' :: forall alg nm f xs conf str . Encoding f nm alg conf str -> Enc xs conf str -> f (Enc (nm ': xs) conf str) runEncoding' (UnsafeMkEncoding _ fn) = fn +-- |+-- Version of @runEncoding'@ function specialized to empty encoding+--+-- @since 0.5.2.0+runEncoding1' :: forall alg nm f conf str . Encoding f nm alg conf str -> Enc ('[] :: [Symbol]) conf str -> f (Enc '[nm] conf str)+runEncoding1' = runEncoding' @alg @nm @f @'[]+ -- | Same as 'runEncoding'' but compiler figures out algorithm name -- -- Using it can slowdown compilation ----- This combinator has @Algorithm nm alg@ constraint (which stands for @TakeUntil ":" nm ~ alg@.--- If rules on @alg@ are relaxed this will just return the /default/ algorithm.+-- This combinator has @Algorithm nm alg@ constraint (which currently stands for @TakeUntil ":" nm ~ alg@. ----- If that happens @-XTypeApplications@ annotations will be needed and @_@ methods will simply --- use default algorithm name.+-- @runEncoding@ functions are typically not used directly, @runEncodings@ functions defined below or @encodeAll@ +-- functions are used instead. --+-- In the following example (and other examples) we use displ convenience function that provides String display of the encoding.+-- The @"r-ban:111"@ allows only strings with 3 characters satisfying alphanumeric bound of '1'+--+-- >>> fmap displ (_runEncoding encFBan $ toEncoding () "000" :: Either EncodeEx (Enc '["r-ban:111"] () T.Text))+-- Right "Enc '[r-ban:111] () (Text 000)"+-- -- @since 0.3.0.0 _runEncoding :: forall nm f xs conf str alg . (Algorithm nm alg) => Encoding f nm alg conf str -> Enc xs conf str -> f (Enc (nm ': xs) conf str) _runEncoding = runEncoding' @(AlgNm nm) + -- | -- HList like construction that defines a list of @Encoding@ elements. --@@ -198,16 +237,35 @@ -- -- @since 0.3.0.0 data Encodings f (nms :: [Symbol]) (algs :: [Symbol]) conf str where- -- | constructor is to be treated as Unsafe to Encode and Decode instance implementations- -- particular encoding instances may expose smart constructors for limited data types ZeroE :: Encodings f '[] '[] conf str- ConsE :: Encoding f nm alg conf str -> Encodings f nms algs conf str -> Encodings f (nm ': nms) (alg ': algs) conf str+ ConsE :: Encoding f nm alg conf str -> Encodings f nms algs conf str -> Encodings f (nm ': nms) (alg ': algs) conf str +infixr 5 -:-+(-:-) :: Encoding f nm alg conf str -> Encodings f nms algs conf str -> Encodings f (nm ': nms) (alg ': algs) conf str+(-:-) = ConsE + -- | -- Runs encodings, requires -XTypeApplication annotation specifying the algorithm(s) ----- >>> runEncodings' @'["r-ban"] encodings . toEncoding () $ ("22") :: Either EncodeEx (Enc '["r-ban:111"] () T.Text)+-- >>> runEncodings' @'["r-ban"] (encFBan -:- ZeroE) . toEncoding () $ "000" :: Either EncodeEx (Enc '["r-ban:111"] () T.Text)+-- Right (UnsafeMkEnc Proxy () "000")+--+-- Polymorphic access to encodings is provided by @EncodeAll@ typeclass so we can simply write:+--+-- >>> runEncodings' @'["r-ban"] encodings . toEncoding () $ "22" :: Either EncodeEx (Enc '["r-ban:111"] () T.Text) -- Left (EncodeEx "r-ban:111" ("Input list has wrong size expecting 3 but length \"22\" == 2"))+--+-- This library also offers backward compatible equivalents @encodeFAll@ to @runEncodings@ functions +-- (see "Data.TypedEncoding.Combinators.Encode") which are basically equivalent to something like+-- @+-- runEncoding' encoding+-- @+--+-- >>> encodeFAll' @'["r-ban"] . toEncoding () $ "111" :: Either EncodeEx (Enc '["r-ban:111"] () T.Text)+-- Right (UnsafeMkEnc Proxy () "111")+--+-- >>> fmap displ . encodeFAll' @'["r-ban"] @'["r-ban:111"] @(Either EncodeEx) @() @T.Text . toEncoding () $ "111"+-- Right "Enc '[r-ban:111] () (Text 111)" -- -- @since 0.3.0.0 runEncodings' :: forall algs nms f c str . (Monad f) => Encodings f nms algs c str -> Enc ('[]::[Symbol]) c str -> f (Enc nms c str)
src/Data/TypedEncoding/Conv/Text.hs view
@@ -27,6 +27,13 @@ ) => Enc xs c String -> Enc xs c T.Text pack = unsafeChangePayload T.pack +-- | simplified version of @pack@ that works on single /r-/ encodings+-- @since 0.5.2.0+pack1 :: (+ Superset "r-UNICODE.D76" y + ) => Enc '[y] c String -> Enc '[y] c T.Text+pack1 = pack+ -- | This assumes that each of the encodings in @xs@ work work equivalently in @String@ and @Text@. -- This is similar to the assumptions made in 'pack'. unpack :: (@@ -36,6 +43,13 @@ , AllEncodeInto "r-UNICODE.D76" encs ) => Enc xs c T.Text -> Enc xs c String unpack = unsafeChangePayload T.unpack ++-- | simplified version of @unpack@ that works on single /r-/ encodings+-- @since 0.5.2.0+unpack1 :: (+ Superset "r-UNICODE.D76" y + ) => Enc '[y] c T.Text -> Enc '[y] c String+unpack1 = unpack -- | -- Text is automatically @"r-UTF8"@ encoded
src/Data/TypedEncoding/Conv/Text/Encoding.hs view
@@ -25,6 +25,7 @@ -- >>> import Test.QuickCheck -- >>> import Test.QuickCheck.Instances.Text() -- >>> import Test.QuickCheck.Instances.ByteString()+-- >>> import Data.TypedEncoding.Instances.Restriction.BoundedAlphaNums() -- >>> import qualified Data.ByteString.Char8 as B8 -- >>> import Data.Char -- >>> import Data.Either@@ -71,7 +72,7 @@ -- >>> displ . utf8Demote . decodeUtf8 $ (unsafeSetPayload () "Hello" :: Enc '["r-UTF8"] () B.ByteString) -- "Enc '[] () (Text Hello)" ----- @decodeUtf8@ and @encodeUtf8@ form isomorphism+-- @decodeUtf8@ and @encodeUtf8@ now form isomorphism -- -- prop> \x -> getPayload x == (getPayload . encodeUtf8 . decodeUtf8 @ '["r-UTF8"] @() $ x) --@@ -87,8 +88,18 @@ -- as any of the "enc-" and "do-" encodings that can be currently found in this library. -- Future versions of this method are likely to introduce constraints that guarantee better type safety. --+--+-- This is technically unsafe (even if we ignore the use of @unsafeSetPayload@) of decodeUtf8 +-- since currently @"r-ban:999"@ does not have @ByteString@ instances and that violates the assumption of matching encoding/decoding stacks+-- on both sides. +-- >>> displ . decodeUtf8 $ (unsafeSetPayload () "123" :: Enc '["r-ban:999"] () B.ByteString)+-- "Enc '[r-ban:999] () (Text 123)"+-- -- See "Data.TypedEncoding.Conv" for more detailed discussion. --+-- Note: implementation uses the partial 'TE.decodeUtf8' function but provides type level guarantee that it this function+-- will not error out unless unsafe combinators were used in constructing the encoded input+-- -- @since 0.4.0.0 decodeUtf8 :: forall xs c t y ys encs. ( Knds.UnSnoc xs ~ '(,) ys y@@ -98,6 +109,13 @@ ) => Enc xs c B.ByteString -> Enc xs c T.Text decodeUtf8 = withUnsafe (fmap TE.decodeUtf8) +-- | simplified version of @decodeUtf8@ that works on single /r-/ encodings+-- @since 0.5.2.0+decodeUtf8_1 :: (+ Superset "r-UTF8" y + ) => Enc '[y] c B.ByteString -> Enc '[y] c T.Text +decodeUtf8_1 = decodeUtf8+ -- | -- >>> displ $ encodeUtf8 $ utf8Promote $ toEncoding () ("text" :: T.Text) -- "Enc '[r-UTF8] () (ByteString text)"@@ -114,3 +132,10 @@ , AllEncodeInto "r-UTF8" encs ) => Enc xs c T.Text -> Enc xs c B.ByteString encodeUtf8 = withUnsafe (fmap TE.encodeUtf8)++-- | simplified version of @decodeUtf8@ that works on single /r-/ encodings+-- @since 0.5.2.0+encodeUtf8_1 :: (+ Superset "r-UTF8" y + ) => Enc '[y] c T.Text -> Enc '[y] c B.ByteString +encodeUtf8_1 = encodeUtf8
src/Data/TypedEncoding/Conv/Text/Lazy.hs view
@@ -20,8 +20,22 @@ ) => Enc xs c String -> Enc xs c TL.Text pack = unsafeChangePayload TL.pack +-- | simplified version of @pack@ that works on single /r-/ encodings+-- @since 0.5.2.0+pack1 :: (+ Superset "r-UNICODE.D76" y + ) => Enc '[y] c String -> Enc '[y] c TL.Text+pack1 = pack+ unpack :: Enc xs c TL.Text -> Enc xs c String unpack = unsafeChangePayload TL.unpack ++-- | simplified version of @unpack@ that works on single /r-/ encodings+-- @since 0.5.2.0+unpack1 :: (+ Superset "r-UNICODE.D76" y + ) => Enc '[y] c TL.Text -> Enc '[y] c String+unpack1 = unpack -- | Text is automatically @"r-UTF8"@ encoded utf8Promote :: Enc xs c TL.Text -> Enc (Snoc xs "r-UTF8") c TL.Text
src/Data/TypedEncoding/Conv/Text/Lazy/Encoding.hs view
@@ -29,6 +29,13 @@ ) => Enc xs c BL.ByteString -> Enc xs c TL.Text decodeUtf8 = withUnsafe (fmap TEL.decodeUtf8) +-- | simplified version of @decodeUtf8@ that works on single /r-/ encodings+-- @since 0.5.2.0+decodeUtf8_1 :: (+ Superset "r-UTF8" y + ) => Enc '[y] c BL.ByteString -> Enc '[y] c TL.Text +decodeUtf8_1 = decodeUtf8+ -- | Lazy version of 'Data.TypedEncoding.Conv.Text.Encoding.encodeUtf8' encodeUtf8 :: forall xs c t y ys encs. ( Knds.UnSnoc xs ~ '(,) ys y@@ -37,3 +44,10 @@ , AllEncodeInto "r-UTF8" encs ) => Enc xs c TL.Text -> Enc xs c BL.ByteString encodeUtf8 = withUnsafe (fmap TEL.encodeUtf8)++-- | simplified version of @decodeUtf8@ that works on single /r-/ encodings+-- @since 0.5.2.0+encodeUtf8_1 :: (+ Superset "r-UTF8" y + ) => Enc '[y] c TL.Text -> Enc '[y] c BL.ByteString +encodeUtf8_1 = encodeUtf8
src/Data/TypedEncoding/Instances/Enc/Base64.hs view
@@ -53,7 +53,10 @@ acceptLenientL = withUnsafeCoerce (BL64.encode . BL64.decodeLenient) -- |--- Validated "r-B64" is guaranteed to decode. +-- Validated "r-B64" is guaranteed to decode.+-- +-- Use flattenAs in the other direction.+-- -- This would not be safe for Text asEncodingB :: Enc '["r-B64"] c B.ByteString -> Enc '["enc-B64"] c B.ByteString asEncodingB = withUnsafeCoerce id@@ -64,17 +67,21 @@ 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--- ------ >>> let tstB64 = encodeAll . toEncoding () $ "Hello World" :: Enc '["enc-B64"] () B.ByteString--- >>> displ (flattenAs tstB64 :: Enc '["r-ASCII"] () B.ByteString)--- "Enc '[r-ASCII] () (ByteString SGVsbG8gV29ybGQ=)"++-- @"enc-B64-nontext"@ is deprecated, use "r-B64" -- -- @since 0.1.0.0 instance FlattenAs "r-ASCII" "enc-B64-nontext" where --- |+-- | allow to treat B64 encodings as ASCII forgetting about B64 encoding.+--+-- Converting to "r-B64" is also an option now.+--+-- >>> let tstB64 = encodeAll . toEncoding () $ "Hello World" :: Enc '["enc-B64"] () B.ByteString+-- >>> displ (flattenAs $ tstB64 :: Enc '["r-ASCII"] () B.ByteString)+-- "Enc '[r-ASCII] () (ByteString SGVsbG8gV29ybGQ=)"+--+-- -- @since 0.1.0.0 instance FlattenAs "r-ASCII" "enc-B64" where
src/Data/TypedEncoding/Instances/Restriction/ASCII.hs view
@@ -14,10 +14,10 @@ -- prop> B8.all ((< 128) . ord) . getPayload @ '["r-ASCII"] @() @B.ByteString -- -- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds--- >>> encodeFAll . toEncoding () $ "Hello World" :: Either EncodeEx (Enc '["r-ASCII"] () T.Text)+-- >>> _runEncodings encodings . toEncoding () $ "Hello World" :: Either EncodeEx (Enc '["r-ASCII"] () T.Text) -- Right (UnsafeMkEnc Proxy () "Hello World") ----- >>> encodeFAll . toEncoding () $ "\194\160" :: Either EncodeEx (Enc '["r-ASCII"] () T.Text)+-- >>> _runEncodings encodings . toEncoding () $ "\194\160" :: Either EncodeEx (Enc '["r-ASCII"] () T.Text) -- Left (EncodeEx "r-ASCII" (NonAsciiChar '\194')) -- -- @since 0.1.0.0
src/Data/TypedEncoding/Instances/Restriction/UTF8.hs view
@@ -58,10 +58,10 @@ -- | UTF8 encodings are defined for ByteString only as that would not make much sense for Text ----- >>> encodeFAll . toEncoding () $ "\xc3\xb1" :: Either EncodeEx (Enc '["r-UTF8"] () B.ByteString)+-- >>> _runEncodings encodings . toEncoding () $ "\xc3\xb1" :: Either EncodeEx (Enc '["r-UTF8"] () B.ByteString) -- Right (UnsafeMkEnc Proxy () "\195\177") ----- >>> encodeFAll . toEncoding () $ "\xc3\x28" :: Either EncodeEx (Enc '["r-UTF8"] () B.ByteString)+-- >>> _runEncodings encodings . toEncoding () $ "\xc3\x28" :: Either EncodeEx (Enc '["r-UTF8"] () B.ByteString) -- Left (EncodeEx "r-UTF8" (Cannot decode byte '\xc3': ... -- -- Following test uses 'verEncoding' helper that checks that bytes are encoded as Right iff they are valid UTF8 bytes
src/Examples/TypedEncoding/Conversions.hs view
@@ -98,10 +98,10 @@ -- * Moving between Text and ByteString eHelloAsciiB :: Either EncodeEx (Enc '["r-ASCII"] () B.ByteString)-eHelloAsciiB = encodeFAll . toEncoding () $ "HeLlo world" +eHelloAsciiB = _runEncodings encodings . toEncoding () $ "HeLlo world" -- ^ Example value to play with ----- >>> encodeFAll . toEncoding () $ "HeLlo world" :: Either EncodeEx (Enc '["r-ASCII"] () B.ByteString) +-- >>> _runEncodings encodings . toEncoding () $ "HeLlo world" :: Either EncodeEx (Enc '["r-ASCII"] () B.ByteString) -- Right (UnsafeMkEnc Proxy () "HeLlo world") Right helloAsciiB = eHelloAsciiB@@ -197,8 +197,7 @@ -- -- >>> :t EncTe.encodeUtf8 helloUtf8B64T -- ...--- ... Couldn't match type ‘IsSupersetOpen--- ... "r-UTF8" "enc-B64" ...+-- ... Couldn't match type ... -- ... -- -- This is not allowed! We need to add the redundant "r-UTF8" back:@@ -223,7 +222,6 @@ -- ... -- ... error: -- ... Couldn't match type ...--- ... "r-UTF8" "enc-B64" ... -- ... -- -- This is good because having the payload inside of @Enc '["enc-B64"] () Text@ would allow us@@ -280,7 +278,7 @@ notTextB64AsTxt :: Enc '["r-B64"] () T.Text-notTextB64AsTxt = EncTe.decodeUtf8 $ flattenAs $ notTextB+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.
src/Examples/TypedEncoding/Overview.hs view
@@ -240,6 +240,11 @@ -- -- Note naming thing: "r-" is partial identity ("r-" is from restriction). --+-- >>> _runEncodings encodings . toEncoding () $ "HeLlo world" :: Either EncodeEx (Enc '["r-ASCII"] () B.ByteString) +-- Right (UnsafeMkEnc Proxy () "HeLlo world")+--+-- or equivalently+-- -- >>> encodeFAll . toEncoding () $ "HeLlo world" :: Either EncodeEx (Enc '["r-ASCII"] () B.ByteString) -- Right (UnsafeMkEnc Proxy () "HeLlo world") helloAscii :: Either EncodeEx (Enc '["r-ASCII"] () B.ByteString)
src/Examples/TypedEncoding/ToEncString.hs view
@@ -77,8 +77,8 @@ -- |--- In this example @toEncString@ converts 'IpV4' to @Enc '["r-IPv4"] Text@.--- +-- In this example @toEncString@ converts our example 'IpV4' type to @Enc '["r-IPv4"] Text@.+-- -- This is done with help of existing @"r-Word8-decimal"@ annotation defined -- in "Data.TypedEncoding.Instances.Restriction.Misc" --
typed-encoding.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: df1ee6c51c573402710616f718103b1f8d79bc8811d5aa416e628c8f30ad927f+-- hash: 085d089a3961a826a165b1612c576bd1bda3176093afa389e3f7e082ac26caeb name: typed-encoding-version: 0.5.1.0+version: 0.5.2.0 synopsis: Type safe string transformations description: See README.md in the project github repository. category: Data, Text@@ -99,7 +99,7 @@ ghc-options: -fwarn-unused-imports -fwarn-incomplete-patterns -fprint-explicit-kinds build-depends: base >=4.10 && <5- , base64-bytestring >=1.0 && <1.1+ , base64-bytestring >=1.0 && <1.3 , bytestring >=0.10 && <0.11 , symbols >=0.3 && <0.3.1 , text >=1.2 && <1.3@@ -116,7 +116,7 @@ build-depends: QuickCheck >=2.13.1 && <2.14 , base >=4.10 && <5- , base64-bytestring >=1.0 && <1.1+ , base64-bytestring >=1.0 && <1.3 , bytestring >=0.10 && <0.11 , doctest >=0.16 && <0.17 , doctest-discover >=0.2 && <0.3@@ -139,7 +139,7 @@ build-depends: QuickCheck >=2.13.1 && <2.14 , base >=4.10 && <5- , base64-bytestring >=1.0 && <1.1+ , base64-bytestring >=1.0 && <1.3 , bytestring >=0.10 && <0.11 , hspec , quickcheck-instances >=0.3.20 && <0.4