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