module PostgreSQLBinary.Decoder.Zepto where
import PostgreSQLBinary.Prelude hiding (take, bool)
import Data.Attoparsec.Zepto
import qualified PostgreSQLBinary.Integral as Integral
import qualified PostgreSQLBinary.Array as Array
import qualified Data.Scientific as Scientific
run :: ByteString -> Parser a -> Either Text a
run input parser =
either (Left . fromString . show) Right $ parse parser input
endOfInput :: Parser ()
endOfInput =
atEnd >>= \case True -> return (); False -> fail "Not an end of input"
intOfSize :: (Integral a, Bits a) => Int -> Parser a
intOfSize x =
Integral.pack <$> take x
array :: Parser Array.Data
array =
do
dimensionsAmountV <- intOfSize 4
nullsV <- nulls
oidV <- intOfSize 4
dimensionsV <- replicateM dimensionsAmountV dimension
valuesV <- many value
return (dimensionsV, valuesV, nullsV, oidV)
where
dimension =
(,) <$> intOfSize 4 <*> intOfSize 4
value =
nothing <|> just
where
nothing =
string (Integral.unpack (1 :: Word32)) *> pure Nothing
just =
Just <$> (take =<< intOfSize 4)
nulls =
(intOfSize 4 :: Parser Word32) >>= \case
0 -> return False
1 -> return True
w -> fail $ "Invalid value: " <> show w