module Argo.Type.Encoder where import qualified Argo.Literal as Literal import qualified Argo.Type.Config as Config import qualified Argo.Type.Indent as Indent import qualified Argo.Vendor.Builder as Builder import qualified Argo.Vendor.Transformers as Trans import qualified Control.Monad as Monad import qualified Data.Functor.Identity as Identity import qualified Data.Semigroup as Semigroup type Encoder = Trans.ReaderT Config.Config (Trans.WriterT Builder.Builder Identity.Identity) unwrap :: Config.Config -> Encoder a -> (a, Builder.Builder) unwrap :: Config -> Encoder a -> (a, Builder) unwrap Config c = Identity (a, Builder) -> (a, Builder) forall a. Identity a -> a Identity.runIdentity (Identity (a, Builder) -> (a, Builder)) -> (Encoder a -> Identity (a, Builder)) -> Encoder a -> (a, Builder) forall b c a. (b -> c) -> (a -> b) -> a -> c . WriterT Builder Identity a -> Identity (a, Builder) forall w (m :: * -> *) a. WriterT w m a -> m (a, w) Trans.runWriterT (WriterT Builder Identity a -> Identity (a, Builder)) -> (Encoder a -> WriterT Builder Identity a) -> Encoder a -> Identity (a, Builder) forall b c a. (b -> c) -> (a -> b) -> a -> c . (Encoder a -> Config -> WriterT Builder Identity a) -> Config -> Encoder a -> WriterT Builder Identity a forall a b c. (a -> b -> c) -> b -> a -> c flip Encoder a -> Config -> WriterT Builder Identity a forall r (m :: * -> *) a. ReaderT r m a -> r -> m a Trans.runReaderT Config c run :: Config.Config -> Encoder a -> Builder.Builder run :: Config -> Encoder a -> Builder run Config c = (a, Builder) -> Builder forall a b. (a, b) -> b snd ((a, Builder) -> Builder) -> (Encoder a -> (a, Builder)) -> Encoder a -> Builder forall b c a. (b -> c) -> (a -> b) -> a -> c . Config -> Encoder a -> (a, Builder) forall a. Config -> Encoder a -> (a, Builder) unwrap Config c list :: Encoder () -> Encoder () -> Encoder () -> (a -> Encoder ()) -> [a] -> Encoder () list :: Encoder () -> Encoder () -> Encoder () -> (a -> Encoder ()) -> [a] -> Encoder () list Encoder () left Encoder () right Encoder () separator a -> Encoder () encode [a] xs = do Encoder () left case [a] xs of [] -> () -> Encoder () forall (f :: * -> *) a. Applicative f => a -> f a pure () a x : [a] ys -> do (Config -> Config) -> Encoder () -> Encoder () forall r (m :: * -> *) a. (r -> r) -> ReaderT r m a -> ReaderT r m a Trans.local Config -> Config Config.increaseLevel (Encoder () -> Encoder ()) -> Encoder () -> Encoder () forall a b. (a -> b) -> a -> b $ do Maybe Builder maybeIndent <- Config -> Maybe Builder makeIndent (Config -> Maybe Builder) -> ReaderT Config (WriterT Builder Identity) Config -> ReaderT Config (WriterT Builder Identity) (Maybe Builder) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> ReaderT Config (WriterT Builder Identity) Config forall (m :: * -> *) r. Monad m => ReaderT r m r Trans.ask Maybe Builder -> Encoder () withNewLine Maybe Builder maybeIndent a -> Encoder () encode a x [a] -> (a -> Encoder ()) -> Encoder () forall (t :: * -> *) (m :: * -> *) a b. (Foldable t, Monad m) => t a -> (a -> m b) -> m () Monad.forM_ [a] ys ((a -> Encoder ()) -> Encoder ()) -> (a -> Encoder ()) -> Encoder () forall a b. (a -> b) -> a -> b $ \a y -> do Encoder () separator Maybe Builder -> Encoder () withNewLine Maybe Builder maybeIndent a -> Encoder () encode a y Maybe Builder maybeIndent <- Config -> Maybe Builder makeIndent (Config -> Maybe Builder) -> ReaderT Config (WriterT Builder Identity) Config -> ReaderT Config (WriterT Builder Identity) (Maybe Builder) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> ReaderT Config (WriterT Builder Identity) Config forall (m :: * -> *) r. Monad m => ReaderT r m r Trans.ask Maybe Builder -> Encoder () withNewLine Maybe Builder maybeIndent Encoder () right makeIndent :: Config.Config -> Maybe Builder.Builder makeIndent :: Config -> Maybe Builder makeIndent Config config = case Config -> Indent Config.indent Config config of Indent.Spaces Int spaces -> if Int spaces Int -> Int -> Bool forall a. Ord a => a -> a -> Bool <= Int 0 then Maybe Builder forall a. Maybe a Nothing else Builder -> Maybe Builder forall a. a -> Maybe a Just (Builder -> Maybe Builder) -> (Builder -> Builder) -> Builder -> Maybe Builder forall b c a. (b -> c) -> (a -> b) -> a -> c . Int -> Builder -> Builder forall b a. (Integral b, Monoid a) => b -> a -> a Semigroup.stimesMonoid (Config -> Int Config.level Config config Int -> Int -> Int forall a. Num a => a -> a -> a * Int spaces) (Builder -> Maybe Builder) -> Builder -> Maybe Builder forall a b. (a -> b) -> a -> b $ Word8 -> Builder Builder.word8 Word8 Literal.space Indent Indent.Tab -> Builder -> Maybe Builder forall a. a -> Maybe a Just (Builder -> Maybe Builder) -> (Builder -> Builder) -> Builder -> Maybe Builder forall b c a. (b -> c) -> (a -> b) -> a -> c . Int -> Builder -> Builder forall b a. (Integral b, Monoid a) => b -> a -> a Semigroup.stimesMonoid (Config -> Int Config.level Config config) (Builder -> Maybe Builder) -> Builder -> Maybe Builder forall a b. (a -> b) -> a -> b $ Word8 -> Builder Builder.word8 Word8 Literal.horizontalTabulation withNewLine :: Maybe Builder.Builder -> Encoder () withNewLine :: Maybe Builder -> Encoder () withNewLine = Encoder () -> (Builder -> Encoder ()) -> Maybe Builder -> Encoder () forall b a. b -> (a -> b) -> Maybe a -> b maybe (() -> Encoder () forall (f :: * -> *) a. Applicative f => a -> f a pure ()) ((Builder -> Encoder ()) -> Maybe Builder -> Encoder ()) -> (Builder -> Encoder ()) -> Maybe Builder -> Encoder () forall a b. (a -> b) -> a -> b $ WriterT Builder Identity () -> Encoder () forall (t :: (* -> *) -> * -> *) (m :: * -> *) a. (MonadTrans t, Monad m) => m a -> t m a Trans.lift (WriterT Builder Identity () -> Encoder ()) -> (Builder -> WriterT Builder Identity ()) -> Builder -> Encoder () forall b c a. (b -> c) -> (a -> b) -> a -> c . Builder -> WriterT Builder Identity () forall (m :: * -> *) w. Monad m => w -> WriterT w m () Trans.tell (Builder -> WriterT Builder Identity ()) -> (Builder -> Builder) -> Builder -> WriterT Builder Identity () forall b c a. (b -> c) -> (a -> b) -> a -> c . Builder -> Builder -> Builder forall a. Monoid a => a -> a -> a mappend (Word8 -> Builder Builder.word8 Word8 Literal.newLine)