module Language.JVM.Attribute
( Attribute (..)
, aInfo
, aName
, IsAttribute (..)
, Code
, codeStackMapTable
, ConstantValue
, Exceptions
, StackMapTable
, BootstrapMethods
, Const
) where
import GHC.Generics (Generic)
import Data.Bifunctor
import Data.Binary
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BL
import Data.Monoid
import Data.Text as Text
import Language.JVM.Constant (ConstantPool,
ConstantRef,
lookupText)
import Language.JVM.Utils (SizedByteString32,
trd,
unSizedByteString)
import Language.JVM.Attribute.BootstrapMethods (BootstrapMethods)
import qualified Language.JVM.Attribute.Code as Code
import Language.JVM.Attribute.ConstantValue (ConstantValue)
import Language.JVM.Attribute.Exceptions (Exceptions)
import Language.JVM.Attribute.StackMapTable (StackMapTable)
data Attribute = Attribute
{ aNameIndex :: ! ConstantRef
, aInfo' :: ! SizedByteString32
} deriving (Show, Eq, Generic)
instance Binary Attribute where
aInfo :: Attribute -> BS.ByteString
aInfo = unSizedByteString . aInfo'
aName :: ConstantPool -> Attribute -> Maybe Text.Text
aName cp as = lookupText (aNameIndex as) cp
newtype Const a b = Const { unConst :: a }
class IsAttribute a where
attrName :: Const Text.Text a
fromAttribute :: Attribute -> Either String a
fromAttribute'
:: ConstantPool
-> Attribute
-> Maybe (Either String a)
fromAttribute' cp as = do
name <- aName cp as
if name == unConst (attrName :: Const Text.Text a) then
return $ fromAttribute as
else Nothing
readFromStrict :: Binary a => Attribute -> Either String a
readFromStrict =
bimap trd trd . decodeOrFail . BL.fromStrict . aInfo
instance IsAttribute Code where
attrName = Const "Code"
fromAttribute = readFromStrict
instance IsAttribute ConstantValue where
attrName = Const "ConstantValue"
fromAttribute = readFromStrict
instance IsAttribute Exceptions where
attrName = Const "Exceptions"
fromAttribute = readFromStrict
instance IsAttribute StackMapTable where
attrName = Const "StackMapTable"
fromAttribute = readFromStrict
instance IsAttribute BootstrapMethods where
attrName = Const "BootstrapMethods"
fromAttribute = readFromStrict
type Code = Code.Code Attribute
codeStackMapTable :: ConstantPool -> Code -> Maybe (Either String BootstrapMethods)
codeStackMapTable cp =
getFirst . foldMap (First . fromAttribute' cp) . Code.attributes