iconv-typed 0.1.0.1 → 0.2.0.0
raw patch · 5 files changed
+193/−92 lines, 5 files
Files
- iconv-typed.cabal +16/−3
- src/Codec/Text/IConv/Typed.hs +10/−57
- src/Codec/Text/IConv/Typed/TH.hs +9/−32
- src/Codec/Text/IConv/Typed/TypeInTypeAPI.hs +82/−0
- src/Codec/Text/IConv/Typed/VerboseAPI.hs +76/−0
iconv-typed.cabal view
@@ -1,5 +1,5 @@ name: iconv-typed-version: 0.1.0.1+version: 0.2.0.0 synopsis: Type safe iconv wrapper homepage: https://github.com/adinapoli/iconv-typed#readme license: BSD3@@ -34,14 +34,23 @@ > import Codec.Text.IConv.Typed > > main :: IO ()- > main = print $ convert (E :: E "UTF-8") (E :: E "LATIN1") "hello"+ > main = print $ convert @"UTF-8" @"LATIN1" "hello" . As a result, this code will compile and run only if the passed encoding resolves to a supported encoding (as retrieved at compile time by calling "iconv -l"). For example, the following won't compile: .- > main = print $ convert (E :: E "UFT-8") (E :: E "LATIN1") "hello"+ > main = print $ convert @"UFT-8" "LATIN1" "hello" . As `UFT` is mispelled.+ .+ Using GHC < 8.0 that doesn't supports `TypeInType`? No problem, we've got you covered!+ .+ > module Main where+ >+ > import Codec.Text.IConv.Typed+ >+ > main :: IO ()+ > main = print $ convert (E :: E "UTF-8") (E :: E "LATIN1") "hello" library hs-source-dirs: src@@ -55,6 +64,10 @@ bytestring default-language: Haskell2010 ghc-options: -Wall+ if impl(ghc >= 8.0)+ other-modules: Codec.Text.IConv.Typed.TypeInTypeAPI+ else+ other-modules: Codec.Text.IConv.Typed.VerboseAPI if os(darwin) other-modules: Codec.Text.IConv.Typed.MacOSX else
src/Codec/Text/IConv/Typed.hs view
@@ -1,11 +1,14 @@+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE KindSignatures #-}-{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}+{-# LANGUAGE CPP #-} module Codec.Text.IConv.Typed ( E(..)+#if __GLASGOW_HASKELL__ > 800+ , Enc(..)+#endif , ValidEncoding , convert , convertFuzzy@@ -20,59 +23,9 @@ import qualified Codec.Text.IConv as I import Codec.Text.IConv.Typed.TH-import Data.ByteString.Lazy-import GHC.TypeLits -$(generateEncodings)-----------------------------------------------------------------------------------convert :: ( KnownSymbol k1- , KnownSymbol k2- , ValidEncoding k1 ~ 'True- , ValidEncoding k2 ~ 'True- )- => E k1 -- ^ Name of input string encoding- -> E k2 -- ^ Name of output string encoding- -> ByteString -- ^ Input text- -> ByteString -- ^ Output text-convert e1 e2 input = I.convert (reifyEncoding e1) (reifyEncoding e2) input-----------------------------------------------------------------------------------convertFuzzy :: ( KnownSymbol k1- , KnownSymbol k2- , ValidEncoding k1 ~ 'True- , ValidEncoding k2 ~ 'True- )- => I.Fuzzy -- ^ Whether to try and transliterate or- -- discard characters with no direct conversion- -> E k1 -- ^ Name of input string encoding- -> E k2 -- ^ Name of output string encoding- -> ByteString -- ^ Input text- -> ByteString -- ^ Output text-convertFuzzy fuzzy fromEncoding toEncoding input =- I.convertFuzzy fuzzy (reifyEncoding fromEncoding) (reifyEncoding toEncoding) input-----------------------------------------------------------------------------------convertStrictly :: ( KnownSymbol k1- , KnownSymbol k2- , ValidEncoding k1 ~ 'True- , ValidEncoding k2 ~ 'True- )- => E k1 -- ^ Name of input string encoding- -> E k2 -- ^ Name of output string encoding- -> ByteString -- ^ Input text- -> Either ByteString I.ConversionError -- ^ Output text or conversion error-convertStrictly fromEncoding toEncoding input =- I.convertStrictly (reifyEncoding fromEncoding) (reifyEncoding toEncoding) input-----------------------------------------------------------------------------------convertLazily :: ( KnownSymbol k1- , KnownSymbol k2- , ValidEncoding k1 ~ 'True- , ValidEncoding k2 ~ 'True- )- => E k1 -- ^ Name of input string encoding- -> E k2 -- ^ Name of output string encoding- -> ByteString -- ^ Input text- -> [I.Span] -- ^ Output text spans-convertLazily fromEncoding toEncoding input = I.convertLazily (reifyEncoding fromEncoding) (reifyEncoding toEncoding) input+#if __GLASGOW_HASKELL__ >= 800+import Codec.Text.IConv.Typed.TypeInTypeAPI+#else+import Codec.Text.IConv.Typed.VerboseAPI+#endif
src/Codec/Text/IConv/Typed/TH.hs view
@@ -5,48 +5,20 @@ module Codec.Text.IConv.Typed.TH where #if defined darwin_HOST_OS-import Codec.Text.IConv.Typed.MacOSX+import Codec.Text.IConv.Typed.MacOSX #else-import Codec.Text.IConv.Typed.Unix+import Codec.Text.IConv.Typed.Unix #endif -import Codec.Text.IConv-import Data.List (foldl')-import Data.Maybe-import qualified Data.Text as T-import GHC.TypeLits-import Language.Haskell.TH-import Text.Read+import GHC.TypeLits+import Language.Haskell.TH data E (k :: Symbol) = E reifyEncoding :: KnownSymbol k => E k -> String reifyEncoding = symbolVal -filterNumericEncoding :: [EncodingName] -> [EncodingName]-filterNumericEncoding = filter (not . numerical)- where- numerical x = isJust (readMaybe x :: Maybe Int)- ---------------------------------------------------------------------------------replacementRules :: [(T.Text, T.Text)]-replacementRules = [ ("-", "__")- , (".", "____")- , (":", "___")- ]-----------------------------------------------------------------------------------applyRule :: T.Text -> (T.Text, T.Text) -> T.Text-applyRule t (input, output) = T.replace input output t-----------------------------------------------------------------------------------convertName :: EncodingName -> EncodingName-convertName = T.unpack . (\t -> foldl' applyRule t replacementRules) . T.pack---- closedTypeFamilyD :: Name -> [TyVarBndr] -> FamilyResultSig -> Maybe InjectivityAnn -> [TySynEqnQ] -> DecQ----------------------------------------------------------------------------------- generateEncodings :: Q [Dec] generateEncodings = do let encs = getAvailableEncodings@@ -54,6 +26,11 @@ let symbol = mkName "Symbol" let validEncoding = mkName "ValidEncoding" let bool = mkName "Bool"+#if __GLASGOW_HASKELL__ >= 800 let instances = flip map encs $ \eName -> do return $ TySynEqn [LitT (StrTyLit eName)] (PromotedT (mkName "True")) (: []) <$> closedTypeFamilyD validEncoding [KindedTV k (ConT symbol)] (KindSig (ConT bool)) Nothing instances+#else+ let instances = flip map encs $ \eName -> TySynEqn [LitT (StrTyLit eName)] (PromotedT (mkName "True"))+ return [ClosedTypeFamilyD validEncoding [KindedTV k (ConT symbol)] (Just $ (ConT bool)) instances]+#endif
+ src/Codec/Text/IConv/Typed/TypeInTypeAPI.hs view
@@ -0,0 +1,82 @@+{-# LANGUAGE TypeInType #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE KindSignatures #-}+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}+module Codec.Text.IConv.Typed.TypeInTypeAPI+ ( E(..)+ , Enc+ , ValidEncoding+ , convert+ , convertFuzzy+ , convertStrictly+ , convertLazily+ -- * Handy re-exports+ , I.reportConversionError+ , I.Fuzzy(..)+ , I.ConversionError(..)+ , I.Span(..)+ ) where++import qualified Codec.Text.IConv as I+import Codec.Text.IConv.Typed.TH+import Data.ByteString.Lazy+import GHC.TypeLits++$(generateEncodings)++type Enc k1 k2 = ByteString++--------------------------------------------------------------------------------+convert :: forall k1 k2. ( KnownSymbol k1+ , KnownSymbol k2+ , ValidEncoding k1 ~ 'True+ , ValidEncoding k2 ~ 'True+ )+ => Enc (k1 :: Symbol) (k2 :: Symbol) -- ^ Input text+ -> ByteString -- ^ Output text+convert input = I.convert (reifyEncoding (E @k1)) (reifyEncoding (E @k2)) input++--------------------------------------------------------------------------------+convertFuzzy :: ( KnownSymbol k1+ , KnownSymbol k2+ , ValidEncoding k1 ~ 'True+ , ValidEncoding k2 ~ 'True+ )+ => I.Fuzzy -- ^ Whether to try and transliterate or+ -- discard characters with no direct conversion+ -> E k1 -- ^ Name of input string encoding+ -> E k2 -- ^ Name of output string encoding+ -> ByteString -- ^ Input text+ -> ByteString -- ^ Output text+convertFuzzy fuzzy fromEncoding toEncoding input =+ I.convertFuzzy fuzzy (reifyEncoding fromEncoding) (reifyEncoding toEncoding) input++--------------------------------------------------------------------------------+convertStrictly :: ( KnownSymbol k1+ , KnownSymbol k2+ , ValidEncoding k1 ~ 'True+ , ValidEncoding k2 ~ 'True+ )+ => E k1 -- ^ Name of input string encoding+ -> E k2 -- ^ Name of output string encoding+ -> ByteString -- ^ Input text+ -> Either ByteString I.ConversionError -- ^ Output text or conversion error+convertStrictly fromEncoding toEncoding input =+ I.convertStrictly (reifyEncoding fromEncoding) (reifyEncoding toEncoding) input++--------------------------------------------------------------------------------+convertLazily :: ( KnownSymbol k1+ , KnownSymbol k2+ , ValidEncoding k1 ~ 'True+ , ValidEncoding k2 ~ 'True+ )+ => E k1 -- ^ Name of input string encoding+ -> E k2 -- ^ Name of output string encoding+ -> ByteString -- ^ Input text+ -> [I.Span] -- ^ Output text spans+convertLazily fromEncoding toEncoding input = I.convertLazily (reifyEncoding fromEncoding) (reifyEncoding toEncoding) input
+ src/Codec/Text/IConv/Typed/VerboseAPI.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE KindSignatures #-}+module Codec.Text.IConv.Typed.VerboseAPI+ ( E(..)+ , ValidEncoding+ , convert+ , convertFuzzy+ , convertStrictly+ , convertLazily+ -- * Handy re-exports+ , I.reportConversionError+ , I.Fuzzy(..)+ , I.ConversionError(..)+ , I.Span(..)+ ) where++import qualified Codec.Text.IConv as I+import Codec.Text.IConv.Typed.TH+import Data.ByteString.Lazy+import GHC.TypeLits++$(generateEncodings)++--------------------------------------------------------------------------------+convert :: ( KnownSymbol k1+ , KnownSymbol k2+ , ValidEncoding k1 ~ 'True+ , ValidEncoding k2 ~ 'True+ )+ => E k1 -- ^ Name of input string encoding+ -> E k2 -- ^ Name of output string encoding+ -> ByteString -- ^ Input text+ -> ByteString -- ^ Output text+convert e1 e2 input = I.convert (reifyEncoding e1) (reifyEncoding e2) input++--------------------------------------------------------------------------------+convertFuzzy :: ( KnownSymbol k1+ , KnownSymbol k2+ , ValidEncoding k1 ~ 'True+ , ValidEncoding k2 ~ 'True+ )+ => I.Fuzzy -- ^ Whether to try and transliterate or+ -- discard characters with no direct conversion+ -> E k1 -- ^ Name of input string encoding+ -> E k2 -- ^ Name of output string encoding+ -> ByteString -- ^ Input text+ -> ByteString -- ^ Output text+convertFuzzy fuzzy fromEncoding toEncoding input =+ I.convertFuzzy fuzzy (reifyEncoding fromEncoding) (reifyEncoding toEncoding) input++--------------------------------------------------------------------------------+convertStrictly :: ( KnownSymbol k1+ , KnownSymbol k2+ , ValidEncoding k1 ~ 'True+ , ValidEncoding k2 ~ 'True+ )+ => E k1 -- ^ Name of input string encoding+ -> E k2 -- ^ Name of output string encoding+ -> ByteString -- ^ Input text+ -> Either ByteString I.ConversionError -- ^ Output text or conversion error+convertStrictly fromEncoding toEncoding input =+ I.convertStrictly (reifyEncoding fromEncoding) (reifyEncoding toEncoding) input++--------------------------------------------------------------------------------+convertLazily :: ( KnownSymbol k1+ , KnownSymbol k2+ , ValidEncoding k1 ~ 'True+ , ValidEncoding k2 ~ 'True+ )+ => E k1 -- ^ Name of input string encoding+ -> E k2 -- ^ Name of output string encoding+ -> ByteString -- ^ Input text+ -> [I.Span] -- ^ Output text spans+convertLazily fromEncoding toEncoding input = I.convertLazily (reifyEncoding fromEncoding) (reifyEncoding toEncoding) input