ribosome-host-0.9.9.9: lib/Ribosome/Host/Data/ApiType.hs
module Ribosome.Host.Data.ApiType where
import Data.Char (isSpace)
import Exon (exon)
import qualified FlatParse.Basic as FlatParse
import FlatParse.Basic (
Result (Err, Fail, OK),
branch,
char,
inSpan,
isLatinLetter,
many_,
optional,
readInt,
runParser,
satisfy,
satisfyASCII,
string,
switch,
takeRest,
withSpan,
(<|>),
)
import Prelude hiding (optional, some, span, try, (<|>))
import Text.Show (showsPrec)
import Ribosome.Host.Class.Msgpack.Decode (MsgpackDecode (fromMsgpack))
-- TODO see if using GADT can move some TH stuff to type level
data ApiPrim =
Boolean
|
Integer
|
Float
|
String
|
Dictionary
|
Object
|
Void
|
LuaRef
deriving stock (Eq, Show)
data ApiType =
Prim ApiPrim
|
Array ApiType (Maybe Int)
|
Ext String
deriving stock (Show, Eq)
polyType :: ApiType -> Bool
polyType = \case
Prim Object -> True
Prim Dictionary -> True
_ -> False
pattern PolyType :: ApiType
pattern PolyType <- (polyType -> True)
type Parser =
FlatParse.Parser Text
ws :: Parser ()
ws =
many_ (satisfy isSpace)
span :: Parser () -> Parser String
span seek =
withSpan seek \ _ sp -> inSpan sp takeRest
prim :: Parser ApiPrim
prim =
$(switch [|
case _ of
"Boolean" -> pure Boolean
"Integer" -> pure Integer
"Float" -> pure Float
"String" -> pure String
"Dictionary" -> pure Dictionary
"Object" -> pure Object
"void" -> pure Void
"LuaRef" -> pure LuaRef
|])
typedArray :: Parser ApiType
typedArray = do
t <- apiType
arity <- optional do
$(char ',')
ws
readInt
pure (Array t arity)
array :: Parser ApiType
array = do
$(string "Array")
branch $(string "Of(") (typedArray <* $(char ')')) (pure (Array (Prim Object) Nothing))
ext :: Parser ApiType
ext =
Ext <$> span (many_ (satisfyASCII isLatinLetter))
apiType :: Parser ApiType
apiType =
array <|> (Prim <$> prim) <|> ext
parseApiType :: ByteString -> Either Text ApiType
parseApiType =
runParser apiType >>> \case
OK a "" -> Right a
OK a u -> Left [exon|Parsed #{toText (showsPrec 11 a "")} but got leftovers: #{decodeUtf8 u}|]
Fail -> Left "fail"
Err e -> Left e
instance MsgpackDecode ApiType where
fromMsgpack =
parseApiType <=< fromMsgpack