packages feed

hs-wayland-scanner-0.1.0: src/Graphics/Wayland/Scanner/Types.hs

{-# LANGUAGE OverloadedStrings #-}
------------------------------------------------------------------------
-- |
-- Module      :  Graphics.Wayland.Scanner.Types
-- Copyright   :  (c) Andrea Rossato 2026
-- License     :  BSD3-style (see LICENSE)
--
-- Maintainer  :  andrea.rossato@unitn.it
-- Stability   :  stable
-- Portability :  portable
--
-- This module exports the AST of the Wayland Message Definition
-- Language.
------------------------------------------------------------------------
module Graphics.Wayland.Scanner.Types where

import Data.Map  (Map)
import Data.Set  (Set)
import Data.Text (Text)

data HwsConfig = HwsConfig
  { genPrefix   :: String
  , hsNameSpace :: String
  , protoRole   :: Role
  , protocols   :: [FilePath]
  , cbitsPrefix :: FilePath
  , srcPrefix   :: FilePath
  } deriving (Show, Read)

data Role = Client | Server deriving (Show, Read, Eq)

type Name = Text

data Protocol = Protocol
  { protoName  :: Name
  , protoDesc  :: Text
  , interfaces :: [Interface]
  } deriving Show

data Interface = Interface
  { ifaceName     :: Name
  , ifaceProtocol :: Name
  , ifaceDesc     :: Name
  , ifaceEvents   :: [Message]
  , ifaceReqs     :: [Message]
  , ifaceEnums    :: [EnumDecl]
  , ifaceVersion  :: Int
  } deriving Show

data Message = Message
  { msgName  :: Name
  , msgDesc  :: Text
  , msgArgs  :: [Arg]
  , msgSince :: Int
  } deriving Show

data ObjectType
  = Typed   Text Name
  | Untyped Text
  deriving (Eq, Show)

data Arg
  = ArgNewId  ObjectType
  | ArgObject ObjectType Bool -- Bool is for allow-null
  | ArgValue  Text WlType
  | ArgArray  Text
  deriving (Eq, Show)

data WlType
  = TInt  (Maybe Name) -- possible enum
  | TUint (Maybe Name) -- possible enum
  | TString Bool       -- Bool is for allow-null
  | TFixed
  | TFd
  deriving (Eq, Show)

data EnumDecl = EnumDecl
  { enumName     :: Name
  , enumDesc     :: Text
  , enumBitfield :: Bool
  , enumValues   :: [EnumEntry]
  } deriving Show

data EnumEntry = EnumEntry
  { entryName   :: Name
  , entryDesc   :: Text
  } deriving Show

data EType = EInt | EUint deriving (Eq, Ord, Show)

type EnumMap = Map Name (Set EType)

data SolvedProtocol = SolvedProtocol
  { solvedProtoName    :: Name
  , solvedProtoDesc    :: Text
  , solvedInterfaces   :: [Interface]
  , solvedDependencies :: [Name]
  , solvedEnums        :: EnumMap
  } deriving Show

-- | In the Wayland Message Definition Language events are messages
-- sent by the server to the client, while requests are messages sent
-- by the client to the server. From the server|client perspective,
-- and the Haskell implementation, the distinction is between received
-- messaged (managed through callbacks implemented via foreign
-- wrappers) and messages to be sent (implemented via foreign
-- functions). So, events are received messages for a client and sent
-- messages for the server, and vice versa. 'RoleRender' is to encode
-- this distinction when rendering the 'SolvedProtocol'.
data RoleRender = RoleRender
  { rrRole           :: Role
  , rrReceiveMsgs    :: [Message]  -- received messages: Client = events  / Server requests
  , rrSendMsgs       :: [Message]  -- messages to send:  Client = requests / Server events
  , rrRequestNameSep :: Text       -- "_" / "_send_"
  , rrStructSuf      :: Text       -- "_listener" / "_interface"
  , rrStructTypeSuf  :: Text       -- "Listener" /  "Interface"
  , rrDefaultCBArgs  :: [Text]     -- Callback default args
  , rrDefaultSmsgArg :: Text       -- Default arg for function sending msgs
  }

-- | A "new_id" is a return type in requests. We retrieve it if needed
-- and remove it from the argument list.
splitArgs :: [Arg] -> (Maybe ObjectType, [Arg])
splitArgs args =
  case [t | ArgNewId t <- args] of
    []  -> (Nothing, args)
    [t] -> (Just  t, filter (not . isNewId) args)
    _   -> error "multiple new_id arguments (unexpected in Wayland)"

isNewId :: Arg -> Bool
isNewId (ArgNewId _) = True
isNewId _            = False

notValue :: Arg -> Bool
notValue (ArgValue _ _) = False
notValue _              = True