module Argo.Type.String where import qualified Argo.Decoder as Decoder import qualified Argo.Literal as Literal import qualified Control.DeepSeq as DeepSeq import qualified Control.Monad as Monad import qualified Data.ByteString as ByteString import qualified Data.ByteString.Builder as Builder import qualified Data.ByteString.Builder.Prim as P import qualified Data.Char as Char import qualified Data.Text as Text import qualified Data.Text.Encoding as Text import qualified Data.Word as Word newtype String = String Text.Text deriving (String -> String -> Bool (String -> String -> Bool) -> (String -> String -> Bool) -> Eq String forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a /= :: String -> String -> Bool $c/= :: String -> String -> Bool == :: String -> String -> Bool $c== :: String -> String -> Bool Eq, Int -> String -> ShowS [String] -> ShowS String -> String (Int -> String -> ShowS) -> (String -> String) -> ([String] -> ShowS) -> Show String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [String] -> ShowS $cshowList :: [String] -> ShowS show :: String -> String $cshow :: String -> String showsPrec :: Int -> String -> ShowS $cshowsPrec :: Int -> String -> ShowS Show) instance DeepSeq.NFData Argo.Type.String.String where rnf :: String -> () rnf (String Text x) = Text -> () forall a. NFData a => a -> () DeepSeq.rnf Text x encode :: Argo.Type.String.String -> Builder.Builder encode :: String -> Builder encode (String Text x) = Word8 -> Builder Builder.word8 Word8 Literal.quotationMark Builder -> Builder -> Builder forall a. Semigroup a => a -> a -> a <> BoundedPrim Word8 -> Text -> Builder Text.encodeUtf8BuilderEscaped BoundedPrim Word8 encodeChar Text x Builder -> Builder -> Builder forall a. Semigroup a => a -> a -> a <> Word8 -> Builder Builder.word8 Word8 Literal.quotationMark encodeChar :: P.BoundedPrim Word.Word8 encodeChar :: BoundedPrim Word8 encodeChar = (Word8 -> Bool) -> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8 forall a. (a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a P.condB (Word8 -> Word8 -> Bool forall a. Eq a => a -> a -> Bool == Word8 Literal.quotationMark) (Word8 -> BoundedPrim Word8 forall a. Word8 -> BoundedPrim a encodeShortEscape Word8 Literal.quotationMark) (BoundedPrim Word8 -> BoundedPrim Word8) -> (BoundedPrim Word8 -> BoundedPrim Word8) -> BoundedPrim Word8 -> BoundedPrim Word8 forall b c a. (b -> c) -> (a -> b) -> a -> c . (Word8 -> Bool) -> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8 forall a. (a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a P.condB (Word8 -> Word8 -> Bool forall a. Eq a => a -> a -> Bool == Word8 Literal.reverseSolidus) (Word8 -> BoundedPrim Word8 forall a. Word8 -> BoundedPrim a encodeShortEscape Word8 Literal.reverseSolidus) (BoundedPrim Word8 -> BoundedPrim Word8) -> (BoundedPrim Word8 -> BoundedPrim Word8) -> BoundedPrim Word8 -> BoundedPrim Word8 forall b c a. (b -> c) -> (a -> b) -> a -> c . (Word8 -> Bool) -> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8 forall a. (a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a P.condB (Word8 -> Word8 -> Bool forall a. Eq a => a -> a -> Bool == Word8 Literal.backspace) (Word8 -> BoundedPrim Word8 forall a. Word8 -> BoundedPrim a encodeShortEscape Word8 Literal.latinSmallLetterB) (BoundedPrim Word8 -> BoundedPrim Word8) -> (BoundedPrim Word8 -> BoundedPrim Word8) -> BoundedPrim Word8 -> BoundedPrim Word8 forall b c a. (b -> c) -> (a -> b) -> a -> c . (Word8 -> Bool) -> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8 forall a. (a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a P.condB (Word8 -> Word8 -> Bool forall a. Eq a => a -> a -> Bool == Word8 Literal.formFeed) (Word8 -> BoundedPrim Word8 forall a. Word8 -> BoundedPrim a encodeShortEscape Word8 Literal.latinSmallLetterF) (BoundedPrim Word8 -> BoundedPrim Word8) -> (BoundedPrim Word8 -> BoundedPrim Word8) -> BoundedPrim Word8 -> BoundedPrim Word8 forall b c a. (b -> c) -> (a -> b) -> a -> c . (Word8 -> Bool) -> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8 forall a. (a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a P.condB (Word8 -> Word8 -> Bool forall a. Eq a => a -> a -> Bool == Word8 Literal.newLine) (Word8 -> BoundedPrim Word8 forall a. Word8 -> BoundedPrim a encodeShortEscape Word8 Literal.latinSmallLetterN) (BoundedPrim Word8 -> BoundedPrim Word8) -> (BoundedPrim Word8 -> BoundedPrim Word8) -> BoundedPrim Word8 -> BoundedPrim Word8 forall b c a. (b -> c) -> (a -> b) -> a -> c . (Word8 -> Bool) -> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8 forall a. (a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a P.condB (Word8 -> Word8 -> Bool forall a. Eq a => a -> a -> Bool == Word8 Literal.carriageReturn) (Word8 -> BoundedPrim Word8 forall a. Word8 -> BoundedPrim a encodeShortEscape Word8 Literal.latinSmallLetterR) (BoundedPrim Word8 -> BoundedPrim Word8) -> (BoundedPrim Word8 -> BoundedPrim Word8) -> BoundedPrim Word8 -> BoundedPrim Word8 forall b c a. (b -> c) -> (a -> b) -> a -> c . (Word8 -> Bool) -> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8 forall a. (a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a P.condB (Word8 -> Word8 -> Bool forall a. Eq a => a -> a -> Bool == Word8 Literal.horizontalTabulation) (Word8 -> BoundedPrim Word8 forall a. Word8 -> BoundedPrim a encodeShortEscape Word8 Literal.latinSmallLetterT) (BoundedPrim Word8 -> BoundedPrim Word8) -> (BoundedPrim Word8 -> BoundedPrim Word8) -> BoundedPrim Word8 -> BoundedPrim Word8 forall b c a. (b -> c) -> (a -> b) -> a -> c . (Word8 -> Bool) -> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8 forall a. (a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a P.condB (Word8 -> Word8 -> Bool forall a. Ord a => a -> a -> Bool < Word8 Literal.space) BoundedPrim Word8 encodeLongEscape (BoundedPrim Word8 -> BoundedPrim Word8) -> BoundedPrim Word8 -> BoundedPrim Word8 forall a b. (a -> b) -> a -> b $ FixedPrim Word8 -> BoundedPrim Word8 forall a. FixedPrim a -> BoundedPrim a P.liftFixedToBounded FixedPrim Word8 P.word8 encodeShortEscape :: Word.Word8 -> P.BoundedPrim a encodeShortEscape :: Word8 -> BoundedPrim a encodeShortEscape Word8 x = FixedPrim a -> BoundedPrim a forall a. FixedPrim a -> BoundedPrim a P.liftFixedToBounded (FixedPrim a -> BoundedPrim a) -> FixedPrim a -> BoundedPrim a forall a b. (a -> b) -> a -> b $ (Word8, Word8) -> a -> (Word8, Word8) forall a b. a -> b -> a const (Word8 Literal.reverseSolidus, Word8 x) (a -> (Word8, Word8)) -> FixedPrim (Word8, Word8) -> FixedPrim a forall (f :: * -> *) b a. Contravariant f => (b -> a) -> f a -> f b P.>$< FixedPrim Word8 P.word8 FixedPrim Word8 -> FixedPrim Word8 -> FixedPrim (Word8, Word8) forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b) P.>*< FixedPrim Word8 P.word8 encodeLongEscape :: P.BoundedPrim Word.Word8 encodeLongEscape :: BoundedPrim Word8 encodeLongEscape = FixedPrim Word8 -> BoundedPrim Word8 forall a. FixedPrim a -> BoundedPrim a P.liftFixedToBounded (FixedPrim Word8 -> BoundedPrim Word8) -> FixedPrim Word8 -> BoundedPrim Word8 forall a b. (a -> b) -> a -> b $ (\ Word8 x -> (Word8 Literal.reverseSolidus, (Word8 Literal.latinSmallLetterU, Word8 -> Word16 word8ToWord16 Word8 x))) (Word8 -> (Word8, (Word8, Word16))) -> FixedPrim (Word8, (Word8, Word16)) -> FixedPrim Word8 forall (f :: * -> *) b a. Contravariant f => (b -> a) -> f a -> f b P.>$< FixedPrim Word8 P.word8 FixedPrim Word8 -> FixedPrim (Word8, Word16) -> FixedPrim (Word8, (Word8, Word16)) forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b) P.>*< FixedPrim Word8 P.word8 FixedPrim Word8 -> FixedPrim Word16 -> FixedPrim (Word8, Word16) forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b) P.>*< FixedPrim Word16 P.word16HexFixed word8ToWord16 :: Word.Word8 -> Word.Word16 word8ToWord16 :: Word8 -> Word16 word8ToWord16 = Word8 -> Word16 forall a b. (Integral a, Num b) => a -> b fromIntegral decode :: Decoder.Decoder Argo.Type.String.String decode :: Decoder String decode = do Word8 -> Decoder () Decoder.word8 Word8 Literal.quotationMark ByteString b1 <- Decoder ByteString Decoder.get Int i <- case ByteString -> Int -> Maybe Int getClose ByteString b1 Int 0 of Maybe Int Nothing -> String -> Decoder Int forall (m :: * -> *) a. MonadFail m => String -> m a fail String "unterminated string" Just Int i -> Int -> Decoder Int forall (f :: * -> *) a. Applicative f => a -> f a pure Int i let (ByteString xs, ByteString b2) = Int -> ByteString -> (ByteString, ByteString) ByteString.splitAt Int i ByteString b1 Bool -> Decoder () -> Decoder () forall (f :: * -> *). Applicative f => Bool -> f () -> f () Monad.when ((Word8 -> Bool) -> ByteString -> Bool ByteString.any (Word8 -> Word8 -> Bool forall a. Ord a => a -> a -> Bool < Word8 Literal.space) ByteString xs) (Decoder () -> Decoder ()) -> Decoder () -> Decoder () forall a b. (a -> b) -> a -> b $ String -> Decoder () forall (m :: * -> *) a. MonadFail m => String -> m a fail String "unescaped control character" ByteString -> Decoder () Decoder.put ByteString b2 Word8 -> Decoder () Decoder.word8 Word8 Literal.quotationMark Decoder () Decoder.spaces case ByteString -> Either UnicodeException Text Text.decodeUtf8' ByteString xs of Left UnicodeException e -> String -> Decoder String forall (m :: * -> *) a. MonadFail m => String -> m a fail (String -> Decoder String) -> String -> Decoder String forall a b. (a -> b) -> a -> b $ UnicodeException -> String forall a. Show a => a -> String show UnicodeException e Right Text x -> case Text -> Maybe Text unescapeText Text x of Maybe Text Nothing -> String -> Decoder String forall (m :: * -> *) a. MonadFail m => String -> m a fail String "invalid escape" Just Text y -> String -> Decoder String forall (f :: * -> *) a. Applicative f => a -> f a pure (String -> Decoder String) -> String -> Decoder String forall a b. (a -> b) -> a -> b $ Text -> String String Text y findAt :: Word.Word8 -> Int -> ByteString.ByteString -> Maybe Int findAt :: Word8 -> Int -> ByteString -> Maybe Int findAt Word8 x Int i = (Int -> Int) -> Maybe Int -> Maybe Int forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap (Int -> Int -> Int forall a. Num a => a -> a -> a + Int i) (Maybe Int -> Maybe Int) -> (ByteString -> Maybe Int) -> ByteString -> Maybe Int forall b c a. (b -> c) -> (a -> b) -> a -> c . Word8 -> ByteString -> Maybe Int ByteString.elemIndex Word8 x (ByteString -> Maybe Int) -> (ByteString -> ByteString) -> ByteString -> Maybe Int forall b c a. (b -> c) -> (a -> b) -> a -> c . Int -> ByteString -> ByteString ByteString.drop Int i countConsecutive :: Word.Word8 -> Int -> ByteString.ByteString -> Int countConsecutive :: Word8 -> Int -> ByteString -> Int countConsecutive Word8 x Int i = ByteString -> Int ByteString.length (ByteString -> Int) -> (ByteString -> ByteString) -> ByteString -> Int forall b c a. (b -> c) -> (a -> b) -> a -> c . (Word8 -> Bool) -> ByteString -> ByteString ByteString.takeWhileEnd (Word8 -> Word8 -> Bool forall a. Eq a => a -> a -> Bool == Word8 x) (ByteString -> ByteString) -> (ByteString -> ByteString) -> ByteString -> ByteString forall b c a. (b -> c) -> (a -> b) -> a -> c . Int -> ByteString -> ByteString ByteString.take Int i getClose :: ByteString.ByteString -> Int -> Maybe Int getClose :: ByteString -> Int -> Maybe Int getClose ByteString b Int i = do Int j <- Word8 -> Int -> ByteString -> Maybe Int findAt Word8 Literal.quotationMark Int i ByteString b let n :: Int n = Word8 -> Int -> ByteString -> Int countConsecutive Word8 Literal.reverseSolidus Int j ByteString b if Int -> Bool forall a. Integral a => a -> Bool even Int n then Int -> Maybe Int forall a. a -> Maybe a Just Int j else ByteString -> Int -> Maybe Int getClose ByteString b (Int -> Maybe Int) -> Int -> Maybe Int forall a b. (a -> b) -> a -> b $ Int j Int -> Int -> Int forall a. Num a => a -> a -> a + Int 1 unescapeText :: Text.Text -> Maybe Text.Text unescapeText :: Text -> Maybe Text unescapeText = (String -> Text) -> Maybe String -> Maybe Text forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap (String -> Text Text.pack (String -> Text) -> ShowS -> String -> Text forall b c a. (b -> c) -> (a -> b) -> a -> c . ShowS combineSurrogatePairs) (Maybe String -> Maybe Text) -> (Text -> Maybe String) -> Text -> Maybe Text forall b c a. (b -> c) -> (a -> b) -> a -> c . String -> Maybe String unescapeString (String -> Maybe String) -> (Text -> String) -> Text -> Maybe String forall b c a. (b -> c) -> (a -> b) -> a -> c . Text -> String Text.unpack combineSurrogatePairs :: Prelude.String -> Prelude.String combineSurrogatePairs :: ShowS combineSurrogatePairs String xs = case String xs of String "" -> String xs Char x : Char y : String zs | Char -> Bool isHighSurrogate Char x Bool -> Bool -> Bool && Char -> Bool isLowSurrogate Char y -> Char -> Char -> Char combineSurrogatePair Char x Char y Char -> ShowS forall a. a -> [a] -> [a] : ShowS combineSurrogatePairs String zs Char x : String ys -> Char x Char -> ShowS forall a. a -> [a] -> [a] : ShowS combineSurrogatePairs String ys combineSurrogatePair :: Char -> Char -> Char combineSurrogatePair :: Char -> Char -> Char combineSurrogatePair Char hi Char lo = Int -> Char Char.chr (Int -> Char) -> Int -> Char forall a b. (a -> b) -> a -> b $ Int 0x10000 Int -> Int -> Int forall a. Num a => a -> a -> a + ((Char -> Int Char.ord Char hi Int -> Int -> Int forall a. Num a => a -> a -> a - Int 0xd800) Int -> Int -> Int forall a. Num a => a -> a -> a * Int 0x400) Int -> Int -> Int forall a. Num a => a -> a -> a + (Char -> Int Char.ord Char lo Int -> Int -> Int forall a. Num a => a -> a -> a - Int 0xdc00) isHighSurrogate :: Char -> Bool isHighSurrogate :: Char -> Bool isHighSurrogate Char x = Char '\xd800' Char -> Char -> Bool forall a. Ord a => a -> a -> Bool <= Char x Bool -> Bool -> Bool && Char x Char -> Char -> Bool forall a. Ord a => a -> a -> Bool <= Char '\xdbff' isLowSurrogate :: Char -> Bool isLowSurrogate :: Char -> Bool isLowSurrogate Char x = Char '\xdc00' Char -> Char -> Bool forall a. Ord a => a -> a -> Bool <= Char x Bool -> Bool -> Bool && Char x Char -> Char -> Bool forall a. Ord a => a -> a -> Bool <= Char '\xdfff' unescapeString :: Prelude.String -> Maybe Prelude.String unescapeString :: String -> Maybe String unescapeString String xs = case String xs of String "" -> String -> Maybe String forall (f :: * -> *) a. Applicative f => a -> f a pure String xs Char '\\' : String ys -> case String ys of String "" -> String -> Maybe String forall (m :: * -> *) a. MonadFail m => String -> m a fail String "empty escape" Char x : String zs -> case Char x of Char '"' -> (Char '"' Char -> ShowS forall a. a -> [a] -> [a] :) ShowS -> Maybe String -> Maybe String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> String -> Maybe String unescapeString String zs Char '\\' -> (Char '\\' Char -> ShowS forall a. a -> [a] -> [a] :) ShowS -> Maybe String -> Maybe String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> String -> Maybe String unescapeString String zs Char '/' -> (Char '/' Char -> ShowS forall a. a -> [a] -> [a] :) ShowS -> Maybe String -> Maybe String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> String -> Maybe String unescapeString String zs Char 'b' -> (Char '\b' Char -> ShowS forall a. a -> [a] -> [a] :) ShowS -> Maybe String -> Maybe String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> String -> Maybe String unescapeString String zs Char 'f' -> (Char '\f' Char -> ShowS forall a. a -> [a] -> [a] :) ShowS -> Maybe String -> Maybe String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> String -> Maybe String unescapeString String zs Char 'n' -> (Char '\n' Char -> ShowS forall a. a -> [a] -> [a] :) ShowS -> Maybe String -> Maybe String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> String -> Maybe String unescapeString String zs Char 'r' -> (Char '\r' Char -> ShowS forall a. a -> [a] -> [a] :) ShowS -> Maybe String -> Maybe String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> String -> Maybe String unescapeString String zs Char 't' -> (Char '\t' Char -> ShowS forall a. a -> [a] -> [a] :) ShowS -> Maybe String -> Maybe String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> String -> Maybe String unescapeString String zs Char 'u' -> case String zs of Char a : Char b : Char c : Char d : String es | Just Char y <- Char -> Char -> Char -> Char -> Maybe Char fromLongEscape Char a Char b Char c Char d -> (Char y Char -> ShowS forall a. a -> [a] -> [a] :) ShowS -> Maybe String -> Maybe String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> String -> Maybe String unescapeString String es String _ -> String -> Maybe String forall (m :: * -> *) a. MonadFail m => String -> m a fail String "invalid long escape" Char _ -> String -> Maybe String forall (m :: * -> *) a. MonadFail m => String -> m a fail String "invalid short escape" Char x : String ys -> (Char x Char -> ShowS forall a. a -> [a] -> [a] :) ShowS -> Maybe String -> Maybe String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> String -> Maybe String unescapeString String ys fromLongEscape :: Char -> Char -> Char -> Char -> Maybe Char fromLongEscape :: Char -> Char -> Char -> Char -> Maybe Char fromLongEscape Char a Char b Char c Char d = do Int w <- Char -> Maybe Int fromHexadecimalDigit Char a Int x <- Char -> Maybe Int fromHexadecimalDigit Char b Int y <- Char -> Maybe Int fromHexadecimalDigit Char c Int z <- Char -> Maybe Int fromHexadecimalDigit Char d Char -> Maybe Char forall (f :: * -> *) a. Applicative f => a -> f a pure (Char -> Maybe Char) -> (Int -> Char) -> Int -> Maybe Char forall b c a. (b -> c) -> (a -> b) -> a -> c . Int -> Char Char.chr (Int -> Maybe Char) -> Int -> Maybe Char forall a b. (a -> b) -> a -> b $ (Int 0x1000 Int -> Int -> Int forall a. Num a => a -> a -> a * Int w) Int -> Int -> Int forall a. Num a => a -> a -> a + (Int 0x100 Int -> Int -> Int forall a. Num a => a -> a -> a * Int x) Int -> Int -> Int forall a. Num a => a -> a -> a + (Int 0x10 Int -> Int -> Int forall a. Num a => a -> a -> a * Int y) Int -> Int -> Int forall a. Num a => a -> a -> a + Int z fromHexadecimalDigit :: Char -> Maybe Int fromHexadecimalDigit :: Char -> Maybe Int fromHexadecimalDigit Char x = if Char -> Bool Char.isHexDigit Char x then Int -> Maybe Int forall a. a -> Maybe a Just (Int -> Maybe Int) -> Int -> Maybe Int forall a b. (a -> b) -> a -> b $ Char -> Int Char.digitToInt Char x else Maybe Int forall a. Maybe a Nothing