{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TypeFamilies #-} module Buf (Buf (..), SizedStr, SizedBuilder) where import Data.Char (intToDigit) import qualified Data.DList as D import Data.Kind (Type) import Data.String import qualified Data.Text as S import Data.Text.Lazy (Text) import qualified Data.Text.Lazy as L import qualified Data.Text.Lazy.Builder as T import qualified Data.Text.Lazy.Builder.Int as T newtype Sized a = Sized {forall a. Sized a -> (a, Int) unSized :: (a, Int)} deriving (Int -> Sized a -> ShowS forall a. Show a => Int -> Sized a -> ShowS forall a. Show a => [Sized a] -> ShowS forall a. Show a => Sized a -> String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [Sized a] -> ShowS $cshowList :: forall a. Show a => [Sized a] -> ShowS show :: Sized a -> String $cshow :: forall a. Show a => Sized a -> String showsPrec :: Int -> Sized a -> ShowS $cshowsPrec :: forall a. Show a => Int -> Sized a -> ShowS Show, Sized a -> Sized a -> Bool Sized a -> Sized a -> Ordering Sized a -> Sized a -> Sized a forall a. Eq a -> (a -> a -> Ordering) -> (a -> a -> Bool) -> (a -> a -> Bool) -> (a -> a -> Bool) -> (a -> a -> Bool) -> (a -> a -> a) -> (a -> a -> a) -> Ord a forall {a}. Ord a => Eq (Sized a) forall a. Ord a => Sized a -> Sized a -> Bool forall a. Ord a => Sized a -> Sized a -> Ordering forall a. Ord a => Sized a -> Sized a -> Sized a min :: Sized a -> Sized a -> Sized a $cmin :: forall a. Ord a => Sized a -> Sized a -> Sized a max :: Sized a -> Sized a -> Sized a $cmax :: forall a. Ord a => Sized a -> Sized a -> Sized a >= :: Sized a -> Sized a -> Bool $c>= :: forall a. Ord a => Sized a -> Sized a -> Bool > :: Sized a -> Sized a -> Bool $c> :: forall a. Ord a => Sized a -> Sized a -> Bool <= :: Sized a -> Sized a -> Bool $c<= :: forall a. Ord a => Sized a -> Sized a -> Bool < :: Sized a -> Sized a -> Bool $c< :: forall a. Ord a => Sized a -> Sized a -> Bool compare :: Sized a -> Sized a -> Ordering $ccompare :: forall a. Ord a => Sized a -> Sized a -> Ordering Ord, Sized a -> Sized a -> Bool forall a. Eq a => Sized a -> Sized a -> Bool forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a /= :: Sized a -> Sized a -> Bool $c/= :: forall a. Eq a => Sized a -> Sized a -> Bool == :: Sized a -> Sized a -> Bool $c== :: forall a. Eq a => Sized a -> Sized a -> Bool Eq) type SizedStr = Sized (D.DList Char) type SizedBuilder = Sized T.Builder instance (IsString a) => IsString (Sized a) where fromString :: String -> Sized a fromString String s = forall a. (a, Int) -> Sized a Sized (forall a. IsString a => String -> a fromString String s, forall (t :: * -> *) a. Foldable t => t a -> Int length String s) instance (Semigroup a) => Semigroup (Sized a) where Sized (a a, Int b) <> :: Sized a -> Sized a -> Sized a <> Sized (a c, Int d) = forall a. (a, Int) -> Sized a Sized (a a forall a. Semigroup a => a -> a -> a <> a c, Int b forall a. Num a => a -> a -> a + Int d) {-# INLINE (<>) #-} instance (Monoid a) => Monoid (Sized a) where mempty :: Sized a mempty = forall a. (a, Int) -> Sized a Sized (forall a. Monoid a => a mempty, Int 0) mappend :: Sized a -> Sized a -> Sized a mappend = forall a. Semigroup a => a -> a -> a (<>) {-# INLINE mappend #-} class (Monoid a) => Buf a where type Output a :: Type str :: String -> a sText :: S.Text -> a sText = forall a. Buf a => String -> a str forall b c a. (b -> c) -> (a -> b) -> a -> c . Text -> String S.unpack lText :: L.Text -> a lText = forall a. Buf a => String -> a str forall b c a. (b -> c) -> (a -> b) -> a -> c . Text -> String L.unpack singleton :: Char -> a digit :: Int -> a digit = forall a. Buf a => Char -> a singleton forall b c a. (b -> c) -> (a -> b) -> a -> c . Int -> Char intToDigit {-# INLINE digit #-} cons :: Char -> a -> a cons Char c a s = forall a. Buf a => Char -> a singleton Char c forall a. Semigroup a => a -> a -> a <> a s {-# INLINE cons #-} repeatN :: Int -> Char -> a repeatN Int n = forall a. Buf a => String -> a str forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a. Int -> a -> [a] replicate Int n size :: a -> Int finalize :: a -> Output a instance Buf SizedStr where type Output SizedStr = String str :: String -> SizedStr str String a = forall a. (a, Int) -> Sized a Sized (forall a. [a] -> DList a D.fromList String a, forall (t :: * -> *) a. Foldable t => t a -> Int length String a) singleton :: Char -> SizedStr singleton Char c = forall a. (a, Int) -> Sized a Sized (forall a. a -> DList a D.singleton Char c, Int 1) finalize :: SizedStr -> Output SizedStr finalize = forall a. DList a -> [a] D.toList forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. (a, b) -> a fst forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a. Sized a -> (a, Int) unSized cons :: Char -> SizedStr -> SizedStr cons Char c (Sized (DList Char r, Int m)) = forall a. (a, Int) -> Sized a Sized (forall a. a -> DList a -> DList a D.cons Char c DList Char r, Int m forall a. Num a => a -> a -> a + Int 1) repeatN :: Int -> Char -> SizedStr repeatN Int n Char c = forall a. (a, Int) -> Sized a Sized (forall a. Int -> a -> DList a D.replicate Int n Char c, Int n) size :: SizedStr -> Int size = forall a b. (a, b) -> b snd forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a. Sized a -> (a, Int) unSized instance Buf SizedBuilder where type Output SizedBuilder = Text str :: String -> SizedBuilder str String a = forall a. (a, Int) -> Sized a Sized (forall a. IsString a => String -> a fromString String a, forall (t :: * -> *) a. Foldable t => t a -> Int length String a) sText :: Text -> SizedBuilder sText Text a = forall a. (a, Int) -> Sized a Sized (Text -> Builder T.fromText Text a, Text -> Int S.length Text a) lText :: Text -> SizedBuilder lText Text a = forall a. (a, Int) -> Sized a Sized (Text -> Builder T.fromLazyText Text a, forall a b. (Integral a, Num b) => a -> b fromIntegral (Text -> Int64 L.length Text a)) singleton :: Char -> SizedBuilder singleton Char c = forall a. (a, Int) -> Sized a Sized (Char -> Builder T.singleton Char c, Int 1) digit :: Int -> SizedBuilder digit Int c = forall a. (a, Int) -> Sized a Sized (forall a. Integral a => a -> Builder T.hexadecimal Int c, Int 1) finalize :: SizedBuilder -> Output SizedBuilder finalize = Builder -> Text T.toLazyText forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. (a, b) -> a fst forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a. Sized a -> (a, Int) unSized size :: SizedBuilder -> Int size = forall a b. (a, b) -> b snd forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a. Sized a -> (a, Int) unSized