Emit.hs 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. {-# LANGUAGE OverloadedStrings #-}
  2. module Data.Adnot.Emit where
  3. import Control.Monad (sequence)
  4. import Data.ByteString.Lazy (ByteString)
  5. import Data.ByteString.Builder
  6. import Data.List (intersperse)
  7. import qualified Data.Map.Strict as M
  8. import Data.Monoid ((<>))
  9. import Data.Text (Text)
  10. import qualified Data.Text as T
  11. import Data.Text.Encoding (encodeUtf8Builder)
  12. import qualified Data.Vector as V
  13. import Data.Adnot.Type
  14. encodeValue :: Value -> ByteString
  15. encodeValue = toLazyByteString . buildValue
  16. buildValue :: Value -> Builder
  17. buildValue (Sum n vs)
  18. | V.null vs = char7 '(' <> buildString n <> char7 ')'
  19. | otherwise =
  20. char7 '(' <> buildString n <> char7 ' ' <> spaceSepArr vs <> char7 ')'
  21. buildValue (Product ps) =
  22. char7 '{' <> buildPairs ps <> char7 '}'
  23. buildValue (List vs) =
  24. char7 '[' <> spaceSepArr vs <> char7 ']'
  25. buildValue (Integer i) = integerDec i
  26. buildValue (Double d) = doubleDec d
  27. buildValue (String t) = buildString t
  28. buildString t
  29. | isValidSymbol t = encodeUtf8Builder t
  30. | otherwise = char7 '"' <> escape t <> char7 '"'
  31. escape :: T.Text -> Builder
  32. escape = T.foldr go mempty
  33. where go '"' r = byteString "\\\"" <> r
  34. go '\n' r = byteString "\\n" <> r
  35. go '\\' r = byteString "\\\\" <> r
  36. go c r = char7 c <> r
  37. spaceSep :: [Builder] -> Builder
  38. spaceSep = mconcat . intersperse (char7 ' ')
  39. spaceSepArr :: Array -> Builder
  40. spaceSepArr = spaceSep . map buildValue . V.toList
  41. buildPairs :: Product -> Builder
  42. buildPairs ps = spaceSep [ go k v | (k, v) <- M.toList ps ]
  43. where go k v = buildString k <> char7 ' ' <> buildValue v