{-# LANGUAGE RankNTypes #-}
{-# language DeriveGeneric #-}
{-# language OverloadedStrings #-}
module JSONL (
jsonlWriteFile, jsonlToLBS
, jsonlBuilder
, jsonLine
, jsonlFromLBS
) where
import System.IO (Handle, IOMode(..), withBinaryFile)
import Data.Aeson (ToJSON(..), FromJSON(..), encode, eitherDecode' )
import qualified Data.ByteString.Builder as BBS (toLazyByteString, Builder, lazyByteString, string7)
import qualified Data.ByteString.Builder.Internal as BBS (hPut, putBuilder)
import qualified Data.ByteString.Internal as BS (c2w)
import qualified Data.ByteString.Lazy as LBS (ByteString, span)
import Prelude hiding (writeFile)
jsonlFromLBS :: FromJSON a => LBS.ByteString -> Either String [a]
jsonlFromLBS :: ByteString -> Either String [a]
jsonlFromLBS = [Either String a] -> Either String [a]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([Either String a] -> Either String [a])
-> (ByteString -> [Either String a])
-> ByteString
-> Either String [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [Either String a]
forall a. FromJSON a => ByteString -> [Either String a]
jsonlFromLBS_
jsonlFromLBS_ :: FromJSON a => LBS.ByteString -> [Either String a]
jsonlFromLBS_ :: ByteString -> [Either String a]
jsonlFromLBS_ = [Either String a] -> ByteString -> [Either String a]
forall a.
FromJSON a =>
[Either String a] -> ByteString -> [Either String a]
go [Either String a]
forall a. Monoid a => a
mempty
where
go :: FromJSON a => [Either String a] -> LBS.ByteString -> [Either String a]
go :: [Either String a] -> ByteString -> [Either String a]
go [Either String a]
acc ByteString
lbs = let
(ByteString
s, ByteString
srest) = (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
LBS.span (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> Word8
BS.c2w Char
'\n') ByteString
lbs
in [Either String a] -> ByteString -> [Either String a]
forall a.
FromJSON a =>
[Either String a] -> ByteString -> [Either String a]
go (ByteString -> Either String a
forall a. FromJSON a => ByteString -> Either String a
eitherDecode' ByteString
s Either String a -> [Either String a] -> [Either String a]
forall a. a -> [a] -> [a]
: [Either String a]
acc) ByteString
srest
jsonlWriteFile :: (Foldable t, ToJSON a) => FilePath -> t a -> IO ()
jsonlWriteFile :: String -> t a -> IO ()
jsonlWriteFile String
fpath t a
xs = String -> Builder -> IO ()
writeFile String
fpath (t a -> Builder
forall (t :: * -> *) a. (Foldable t, ToJSON a) => t a -> Builder
jsonlBuilder t a
xs)
jsonlToLBS :: (Foldable t, ToJSON a) => t a -> LBS.ByteString
jsonlToLBS :: t a -> ByteString
jsonlToLBS t a
xs = Builder -> ByteString
BBS.toLazyByteString (Builder -> ByteString) -> Builder -> ByteString
forall a b. (a -> b) -> a -> b
$ t a -> Builder
forall (t :: * -> *) a. (Foldable t, ToJSON a) => t a -> Builder
jsonlBuilder t a
xs
jsonlBuilder :: (Foldable t, ToJSON a) => t a -> BBS.Builder
jsonlBuilder :: t a -> Builder
jsonlBuilder = (a -> Builder) -> t a -> Builder
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> Builder
forall a. ToJSON a => a -> Builder
jsonLine
jsonLine :: ToJSON a => a -> BBS.Builder
jsonLine :: a -> Builder
jsonLine a
x = a -> Builder
forall a. ToJSON a => a -> Builder
jsonToBuilder a
x Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> String -> Builder
BBS.string7 String
"\n"
jsonToBuilder :: ToJSON a => a -> BBS.Builder
jsonToBuilder :: a -> Builder
jsonToBuilder = ByteString -> Builder
BBS.lazyByteString (ByteString -> Builder) -> (a -> ByteString) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> ByteString
forall a. ToJSON a => a -> ByteString
encode
hPutBuilder :: Handle -> BBS.Builder -> IO ()
hPutBuilder :: Handle -> Builder -> IO ()
hPutBuilder Handle
h = Handle -> Put () -> IO ()
forall a. Handle -> Put a -> IO a
BBS.hPut Handle
h (Put () -> IO ()) -> (Builder -> Put ()) -> Builder -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Put ()
BBS.putBuilder
modifyFile :: IOMode -> FilePath -> BBS.Builder -> IO ()
modifyFile :: IOMode -> String -> Builder -> IO ()
modifyFile IOMode
mode String
f Builder
bld = String -> IOMode -> (Handle -> IO ()) -> IO ()
forall r. String -> IOMode -> (Handle -> IO r) -> IO r
withBinaryFile String
f IOMode
mode (Handle -> Builder -> IO ()
`hPutBuilder` Builder
bld)
writeFile :: FilePath -> BBS.Builder -> IO ()
writeFile :: String -> Builder -> IO ()
writeFile = IOMode -> String -> Builder -> IO ()
modifyFile IOMode
WriteMode