packages feed

enum-utf8 (empty) → 0.1.0.0

raw patch · 6 files changed

+287/−0 lines, 6 filesdep +arraydep +basedep +bytestringsetup-changed

Dependencies added: array, base, bytestring, hashable, possibly, render-utf8, unordered-containers

Files

+ ChangeLog.md view
@@ -0,0 +1,3 @@+# 0.1.0.0++  * first release
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Chris Dornan (c) 2019++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Chris Dornan nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,37 @@+# enum-utf8++An experimental toolkit for rendering enumerated types into `Utf8` from+the [`render-utf8`](http://hackage.haskell.org/package/render-utf8) package)+and parsing them back again with the provided `Utf8Parsable` type class.+It is based on the `render-utf8` and+[`enum-text`](http://hackage.haskell.org/package/enum-text) packages.++To get the `Buildable` and `TextParsable` instances for an enumerated data type+use the following pattern:++```+import Text.Enum.Utf8+import Text.Utf8++data Foo = FOO_bar | FOO_bar_baz+  deriving (Bounded,Enum,Eq,Ord,Show)++instance EnumUtf8     Foo+instance Renderable   Foo where render    = renderEnumUtf8+instance Utf8Parsable Foo where parseUtf8 = parseEnumUtf8++main :: IO ()+main = mapM_ (cvtLn . render) [minBound..maxBound::Foo]+```++This will use the default configuration for generating the text of each+enumeration from the derived `show` text, namely:++  * removing the prefix upto and including the first underscore (`_`);+  * converting each subsequent underscore (`_`) into a dash (`-`).++See the Haddocks for details on how to override this default configuration for+any given enumeration type.++Functions for generating and parsing UTF-8 encoded ByteStrings (suitable for+cassava), as are `Hashable` functions.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ enum-utf8.cabal view
@@ -0,0 +1,46 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.31.1.+--+-- see: https://github.com/sol/hpack+--+-- hash: e211f4d5f7164b70e08701690bca40f5199d475d0d41b94e006c0e44404db94f++name:           enum-utf8+version:        0.1.0.0+synopsis:       An experimental Utf8 parsing toolkit for enumerated types+description:    An experimental Utf8 rendering and parsing toolkit for enumerated types based on enum-text and render-utf8. Please see the README on GitHub at <https://github.com/cdornan/enum-text#readme>+category:       Text+homepage:       https://github.com/cdornan/enum-text#readme+bug-reports:    https://github.com/cdornan/enum-text/issues+author:         Chris Dornan+maintainer:     chris@chrisdornan.com+copyright:      2019 Chris Dornan+license:        BSD3+license-file:   LICENSE+build-type:     Simple+extra-source-files:+    README.md+    ChangeLog.md++source-repository head+  type: git+  location: https://github.com/cdornan/enum-text++library+  exposed-modules:+      Text.Enum.Utf8+  other-modules:+      Paths_enum_utf8+  hs-source-dirs:+      src+  ghc-options: -Wall+  build-depends:+      array+    , base >=4.8.2 && <10+    , bytestring+    , hashable+    , possibly+    , render-utf8+    , unordered-containers+  default-language: Haskell2010
+ src/Text/Enum/Utf8.hs view
@@ -0,0 +1,169 @@+{-# LANGUAGE OverloadedStrings    #-}+{-# LANGUAGE RecordWildCards      #-}+{-# LANGUAGE ScopedTypeVariables  #-}++module Text.Enum.Utf8+  ( EnumUtf8(..)+  , Utf8Parsable(..)+  , EnumUtf8Config(..)+  , defaultEnumUtf8Config+  ) where++import           Data.Array+import qualified Data.ByteString.Char8          as B+import qualified Data.ByteString.Lazy           as BL+import qualified Data.ByteString.Builder        as BB+import           Data.Coerce+import           Data.Hashable+import           Data.Possibly+import qualified Data.HashMap.Strict            as HM+import           Data.String+import           Text.Utf8+++-- | a class for 'T.Text' parsers.+class Utf8Parsable a where+  parseUtf8 :: Utf8 -> Possibly a++{- | our toolkit for enumerated types which should be defined as follows:++@+import Text.Enum.Utf8+import Text.Utf8++data Foo = FOO_bar | FOO_bar_baz+  deriving (Bounded,Enum,Eq,Ord,Show)++instance EnumUtf8     Foo+instance Renderable   Foo where render    = renderEnumUtf8+instance Utf8Parsable Foo where parseUtf8 = parseEnumUtf8++main :: IO ()+main = mapM_ (cvtLn . render) [minBound..maxBound::Foo]+@++-}+class ( Renderable    e+      , Bounded       e+      , Enum          e+      , Eq            e+      , Ord           e+      , Show          e+      , Utf8Parsable  e+      ) => EnumUtf8 e where++  -- | Configures the textual representation of @e@ generated by renderEnumUtf8.+  configEnumUtf8 :: e -> EnumUtf8Config+  configEnumUtf8 _ = defaultEnumUtf8Config++  -- | Generate the standard textual representation according to+  -- 'configEnumUtf8' by default.+  renderEnumUtf8 :: e -> Utf8+  renderEnumUtf8 e = enumUtf8Array ! I e++  -- | Parses an @e@ according to the 'renderEnumUtf8' render.+  parseEnumUtf8 :: Utf8 -> Possibly e+  parseEnumUtf8 u = maybe (Left m) Right $ HM.lookup b hashmap_b+    where+      m = "parseEnumUtf8: enumeration not recognised: "++show b+      b = utf8_to_bs u++  -- | A cassava field encoder, using 'the renderEnumUtf8' format.+  toFieldEnumUtf8 :: e -> B.ByteString+  toFieldEnumUtf8 e = enumByteStringArray ! I e++  -- | A cassava field parser using the 'renderEnumUtf8' format.+  fromFieldEnumUtf8_ :: Monad m => B.ByteString -> m e+  fromFieldEnumUtf8_ bs = maybe (fail msg) return $ HM.lookup bs hashmap_b+    where+      msg = "fromFieldEnumUtf8_: enumeration not recognised: "++show bs++  -- | For hashing @e@ with the 'renderEnumUtf8' representation.+  hashWithSaltEnumUtf8 :: Int -> e -> Int+  hashWithSaltEnumUtf8 n = hashWithSalt n . toFieldEnumUtf8+++-------------------------------------------------------------------------------+-- EnumUtf8Config, defaultEnumUtf8Config+-------------------------------------------------------------------------------++-- | configures the default implementation of 'renderEnumUtf8'+data EnumUtf8Config =+  EnumUtf8Config+    { _etc_text_prep :: String -> String  -- ^ applied to the output of 'show';+                                          -- by default strips each data+                                          -- constructor up to and including+                                          -- the first '_'+    , _etc_char_prep :: Char -> Char      -- ^ applied to each character of+                                          -- the outpout of '_etc_text_prep'+    }++defaultEnumUtf8Config :: EnumUtf8Config+defaultEnumUtf8Config =+  EnumUtf8Config+    { _etc_text_prep = defaultTextPrep+    , _etc_char_prep = defaultCharPrep+    }++defaultTextPrep :: String -> String+defaultTextPrep s =+  case dropWhile (/='_') s of+    _:rst@(_:_) -> fromString rst+    _ -> error $ "defaultTextPrep: bad data constructor: "++s++defaultCharPrep :: Char -> Char+defaultCharPrep c = case c of+    '_' -> '-'+    _   -> c+++-------------------------------------------------------------------------------+-- arrays+-------------------------------------------------------------------------------++newtype I a = I { _I :: a }+  deriving (Eq,Ord)++instance EnumUtf8 e => Ix (I e) where+  range   (l,h)   = coerce [_I l.._I h]+  index   (l,_) x = fromEnum (_I x) - fromEnum (_I l)+  inRange (l,h) x = _I l <= _I x && _I x <= _I h++-- | array of texts constructed with 'configEnumUtf8'+enumUtf8Array :: forall e . EnumUtf8 e => Array (I e) Utf8+enumUtf8Array =+    listArray (I minBound,I maxBound)+      [ fromString $ map _etc_char_prep $ _etc_text_prep $ show e+        | e <- [minBound..maxBound :: e]+        ]+  where+    EnumUtf8Config{..} = configEnumUtf8 (minBound :: e)++-- | array of 'B.ByteString' generated from 'renderEnumUtf8'+enumByteStringArray :: forall e . EnumUtf8 e => Array (I e) B.ByteString+enumByteStringArray =+  listArray (I minBound,I maxBound)+    [ utf8_to_bs $ renderEnumUtf8 e+      | e <- [minBound..maxBound :: e]+      ]+++-------------------------------------------------------------------------------+-- hashmap+-------------------------------------------------------------------------------++-- | 'B.ByteString' 'HM.HashMap' based on 'renderEnumUtf8' representation+hashmap_b :: EnumUtf8 e => HM.HashMap B.ByteString e+hashmap_b =+  HM.fromList+    [ (utf8_to_bs $ renderEnumUtf8 c,c)+      | c <- [minBound..maxBound]+      ]+++-------------------------------------------------------------------------------+-- utf8_to_bs+-------------------------------------------------------------------------------++utf8_to_bs :: Utf8 -> B.ByteString+utf8_to_bs = BL.toStrict . BB.toLazyByteString . coerce