    module Data.GI.GIR.Arg
        ( Arg(..)
        , Direction(..)
        , Scope(..)
        , parseArg
        , parseTransfer
        , parseTransferString
        ) where

    #if !MIN_VERSION_base(4,11,0)
    import Data.Monoid ((<>))
    #endif
    import Data.Text (Text)

    import Data.GI.GIR.BasicTypes (Transfer(..), Type)
    import Data.GI.GIR.Parser
    import Data.GI.GIR.Type (parseType, queryElementCType)

    data Direction = DirectionIn
                   | DirectionOut
                   | DirectionInout
                     deriving (Int -> Direction -> ShowS
    [Direction] -> ShowS
    Direction -> String
    (Int -> Direction -> ShowS)
    -> (Direction -> String)
    -> ([Direction] -> ShowS)
    -> Show Direction
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Direction -> ShowS
    showsPrec :: Int -> Direction -> ShowS
    $cshow :: Direction -> String
    show :: Direction -> String
    $cshowList :: [Direction] -> ShowS
    showList :: [Direction] -> ShowS
    Show, Direction -> Direction -> Bool
    (Direction -> Direction -> Bool)
    -> (Direction -> Direction -> Bool) -> Eq Direction
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Direction -> Direction -> Bool
    == :: Direction -> Direction -> Bool
    $c/= :: Direction -> Direction -> Bool
    /= :: Direction -> Direction -> Bool
    Eq, Eq Direction
    Eq Direction =>
    (Direction -> Direction -> Ordering)
    -> (Direction -> Direction -> Bool)
    -> (Direction -> Direction -> Bool)
    -> (Direction -> Direction -> Bool)
    -> (Direction -> Direction -> Bool)
    -> (Direction -> Direction -> Direction)
    -> (Direction -> Direction -> Direction)
    -> Ord Direction
    Direction -> Direction -> Bool
    Direction -> Direction -> Ordering
    Direction -> Direction -> Direction
    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
    $ccompare :: Direction -> Direction -> Ordering
    compare :: Direction -> Direction -> Ordering
    $c< :: Direction -> Direction -> Bool
    < :: Direction -> Direction -> Bool
    $c<= :: Direction -> Direction -> Bool
    <= :: Direction -> Direction -> Bool
    $c> :: Direction -> Direction -> Bool
    > :: Direction -> Direction -> Bool
    $c>= :: Direction -> Direction -> Bool
    >= :: Direction -> Direction -> Bool
    $cmax :: Direction -> Direction -> Direction
    max :: Direction -> Direction -> Direction
    $cmin :: Direction -> Direction -> Direction
    min :: Direction -> Direction -> Direction
    Ord)

    data Scope = ScopeTypeInvalid
               | ScopeTypeCall
               | ScopeTypeAsync
               | ScopeTypeNotified
               | ScopeTypeForever
                 deriving (Int -> Scope -> ShowS
    [Scope] -> ShowS
    Scope -> String
    (Int -> Scope -> ShowS)
    -> (Scope -> String) -> ([Scope] -> ShowS) -> Show Scope
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Scope -> ShowS
    showsPrec :: Int -> Scope -> ShowS
    $cshow :: Scope -> String
    show :: Scope -> String
    $cshowList :: [Scope] -> ShowS
    showList :: [Scope] -> ShowS
    Show, Scope -> Scope -> Bool
    (Scope -> Scope -> Bool) -> (Scope -> Scope -> Bool) -> Eq Scope
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Scope -> Scope -> Bool
    == :: Scope -> Scope -> Bool
    $c/= :: Scope -> Scope -> Bool
    /= :: Scope -> Scope -> Bool
    Eq, Eq Scope
    Eq Scope =>
    (Scope -> Scope -> Ordering)
    -> (Scope -> Scope -> Bool)
    -> (Scope -> Scope -> Bool)
    -> (Scope -> Scope -> Bool)
    -> (Scope -> Scope -> Bool)
    -> (Scope -> Scope -> Scope)
    -> (Scope -> Scope -> Scope)
    -> Ord Scope
    Scope -> Scope -> Bool
    Scope -> Scope -> Ordering
    Scope -> Scope -> Scope
    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
    $ccompare :: Scope -> Scope -> Ordering
    compare :: Scope -> Scope -> Ordering
    $c< :: Scope -> Scope -> Bool
    < :: Scope -> Scope -> Bool
    $c<= :: Scope -> Scope -> Bool
    <= :: Scope -> Scope -> Bool
    $c> :: Scope -> Scope -> Bool
    > :: Scope -> Scope -> Bool
    $c>= :: Scope -> Scope -> Bool
    >= :: Scope -> Scope -> Bool
    $cmax :: Scope -> Scope -> Scope
    max :: Scope -> Scope -> Scope
    $cmin :: Scope -> Scope -> Scope
    min :: Scope -> Scope -> Scope
    Ord)

    data Arg = Arg {
            Arg -> Text
    argCName :: Text,  -- ^ "C" name for the argument. For a
                               -- escaped name valid in Haskell code, use
                               -- `GI.SymbolNaming.escapedArgName`.
            Arg -> Type
    argType :: Type,
            Arg -> Maybe Text
    argCType :: Maybe Text,
            Arg -> Direction
    direction :: Direction,
            Arg -> Bool
    mayBeNull :: Bool,
            Arg -> Documentation
    argDoc :: Documentation,
            Arg -> Scope
    argScope :: Scope,
            Arg -> Int
    argClosure :: Int,
            Arg -> Int
    argDestroy :: Int,
            Arg -> Bool
    argCallerAllocates :: Bool,
            Arg -> Bool
    argCallbackUserData :: Bool,
            -- ^ Whether the argument is an "user-data" argument for a callback.
            Arg -> Transfer
    transfer :: Transfer
        } deriving (Int -> Arg -> ShowS
    [Arg] -> ShowS
    Arg -> String
    (Int -> Arg -> ShowS)
    -> (Arg -> String) -> ([Arg] -> ShowS) -> Show Arg
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Arg -> ShowS
    showsPrec :: Int -> Arg -> ShowS
    $cshow :: Arg -> String
    show :: Arg -> String
    $cshowList :: [Arg] -> ShowS
    showList :: [Arg] -> ShowS
    Show, Arg -> Arg -> Bool
    (Arg -> Arg -> Bool) -> (Arg -> Arg -> Bool) -> Eq Arg
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Arg -> Arg -> Bool
    == :: Arg -> Arg -> Bool
    $c/= :: Arg -> Arg -> Bool
    /= :: Arg -> Arg -> Bool
    Eq, Eq Arg
    Eq Arg =>
    (Arg -> Arg -> Ordering)
    -> (Arg -> Arg -> Bool)
    -> (Arg -> Arg -> Bool)
    -> (Arg -> Arg -> Bool)
    -> (Arg -> Arg -> Bool)
    -> (Arg -> Arg -> Arg)
    -> (Arg -> Arg -> Arg)
    -> Ord Arg
    Arg -> Arg -> Bool
    Arg -> Arg -> Ordering
    Arg -> Arg -> Arg
    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
    $ccompare :: Arg -> Arg -> Ordering
    compare :: Arg -> Arg -> Ordering
    $c< :: Arg -> Arg -> Bool
    < :: Arg -> Arg -> Bool
    $c<= :: Arg -> Arg -> Bool
    <= :: Arg -> Arg -> Bool
    $c> :: Arg -> Arg -> Bool
    > :: Arg -> Arg -> Bool
    $c>= :: Arg -> Arg -> Bool
    >= :: Arg -> Arg -> Bool
    $cmax :: Arg -> Arg -> Arg
    max :: Arg -> Arg -> Arg
    $cmin :: Arg -> Arg -> Arg
    min :: Arg -> Arg -> Arg
    Ord)

    parseTransferString :: Text -> Parser Transfer
    parseTransferString :: Text -> Parser Transfer
    parseTransferString Text
    transfer = case Text
    transfer of
                    Text
    "none" -> Transfer -> Parser Transfer
    forall a. a -> ReaderT ParseContext (Except Text) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Transfer
    TransferNothing
                    Text
    "container" -> Transfer -> Parser Transfer
    forall a. a -> ReaderT ParseContext (Except Text) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Transfer
    TransferContainer
                    Text
    "full" -> Transfer -> Parser Transfer
    forall a. a -> ReaderT ParseContext (Except Text) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Transfer
    TransferEverything
                    Text
    t -> Text -> Parser Transfer
    forall a. Text -> Parser a
    parseError (Text -> Parser Transfer) -> Text -> Parser Transfer
    forall a b. (a -> b) -> a -> b
    $ Text
    "Unknown transfer type \"" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    t Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "\""

    parseTransfer :: Parser Transfer
    parseTransfer :: Parser Transfer
    parseTransfer = Name -> Parser Text
    getAttr Name
    "transfer-ownership" Parser Text -> (Text -> Parser Transfer) -> Parser Transfer
    forall a b.
    ReaderT ParseContext (Except Text) a
    -> (a -> ReaderT ParseContext (Except Text) b)
    -> ReaderT ParseContext (Except Text) b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Text -> Parser Transfer
    parseTransferString

    parseScope :: Text -> Parser Scope
    parseScope :: Text -> Parser Scope
    parseScope Text
    "call" = Scope -> Parser Scope
    forall a. a -> ReaderT ParseContext (Except Text) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Scope
    ScopeTypeCall
    parseScope Text
    "async" = Scope -> Parser Scope
    forall a. a -> ReaderT ParseContext (Except Text) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Scope
    ScopeTypeAsync
    parseScope Text
    "notified" = Scope -> Parser Scope
    forall a. a -> ReaderT ParseContext (Except Text) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Scope
    ScopeTypeNotified
    parseScope Text
    "forever" = Scope -> Parser Scope
    forall a. a -> ReaderT ParseContext (Except Text) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Scope
    ScopeTypeForever
    parseScope Text
    s = Text -> Parser Scope
    forall a. Text -> Parser a
    parseError (Text -> Parser Scope) -> Text -> Parser Scope
    forall a b. (a -> b) -> a -> b
    $ Text
    "Unknown scope type \"" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    s Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "\""

    parseDirection :: Text -> Parser Direction
    parseDirection :: Text -> Parser Direction
    parseDirection Text
    "in" = Direction -> Parser Direction
    forall a. a -> ReaderT ParseContext (Except Text) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Direction
    DirectionIn
    parseDirection Text
    "out" = Direction -> Parser Direction
    forall a. a -> ReaderT ParseContext (Except Text) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Direction
    DirectionOut
    parseDirection Text
    "inout" = Direction -> Parser Direction
    forall a. a -> ReaderT ParseContext (Except Text) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Direction
    DirectionInout
    parseDirection Text
    d = Text -> Parser Direction
    forall a. Text -> Parser a
    parseError (Text -> Parser Direction) -> Text -> Parser Direction
    forall a b. (a -> b) -> a -> b
    $ Text
    "Unknown direction \"" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    d Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "\""

    parseArg :: Parser Arg
    parseArg :: Parser Arg
    parseArg = do
      name <- Name -> Parser Text
    getAttr Name
    "name"
      ownership <- parseTransfer
      scope <- optionalAttr "scope" ScopeTypeInvalid parseScope
      d <- optionalAttr "direction" DirectionIn parseDirection
      closure <- optionalAttr "closure" (-1) parseIntegral
      destroy <- optionalAttr "destroy" (-1) parseIntegral
      nullable <- optionalAttr "nullable" False parseBool
      allowNone <- optionalAttr "allow-none" False parseBool
      -- "allow-none" is deprecated, but still produced by Vala. Support
      -- it for in arguments.
      let mayBeNull = if Direction
    d Direction -> Direction -> Bool
    forall a. Eq a => a -> a -> Bool
    == Direction
    DirectionIn
                      then Bool
    nullable Bool -> Bool -> Bool
    || Bool
    allowNone
                      else Bool
    nullable
      callerAllocates <- optionalAttr "caller-allocates" False parseBool
      -- There is no annotation for this one yet, see
      -- https://gitlab.gnome.org/GNOME/gobject-introspection/-/issues/450
      -- We will use some heuristics later for setting this field.
      let callbackUserData = Bool
    False
      t <- parseType
      maybeCType <- queryElementCType
      doc <- parseDocumentation
      return $ Arg { argCName = name
                   , argType = t
                   , argCType = maybeCType
                   , argDoc = doc
                   , direction = d
                   , mayBeNull = mayBeNull
                   , argScope = scope
                   , argClosure = closure
                   , argDestroy = destroy
                   , argCallerAllocates = callerAllocates
                   , argCallbackUserData = callbackUserData
                   , transfer = ownership
                   }