feat: Field and attribute parsing
This commit is contained in:
parent
62b537a93f
commit
f9fbedc87a
8 changed files with 136 additions and 7 deletions
|
@ -28,13 +28,16 @@ library
|
||||||
Data.Enum.Util
|
Data.Enum.Util
|
||||||
Data.Hex
|
Data.Hex
|
||||||
Language.Java.Classfile
|
Language.Java.Classfile
|
||||||
|
Language.Java.Classfile.Attributes
|
||||||
Language.Java.Classfile.ClassFlag
|
Language.Java.Classfile.ClassFlag
|
||||||
Language.Java.Classfile.ConstantPool
|
Language.Java.Classfile.ConstantPool
|
||||||
Language.Java.Classfile.ConstantPool.Entry
|
Language.Java.Classfile.ConstantPool.Entry
|
||||||
Language.Java.Classfile.ConstantPool.References
|
Language.Java.Classfile.ConstantPool.References
|
||||||
Language.Java.Classfile.Extract
|
Language.Java.Classfile.Extract
|
||||||
Language.Java.Classfile.Extractable
|
Language.Java.Classfile.Extractable
|
||||||
|
Language.Java.Classfile.Extractable.SizedBytes
|
||||||
Language.Java.Classfile.Extractable.WithTag
|
Language.Java.Classfile.Extractable.WithTag
|
||||||
|
Language.Java.Classfile.Fields
|
||||||
Language.Java.Classfile.Flag
|
Language.Java.Classfile.Flag
|
||||||
Language.Java.Classfile.Flags
|
Language.Java.Classfile.Flags
|
||||||
Language.Java.Classfile.FromBigEndian
|
Language.Java.Classfile.FromBigEndian
|
||||||
|
|
|
@ -10,6 +10,7 @@ import Language.Java.Classfile.Flags (Flags)
|
||||||
import Language.Java.Classfile.ClassFlag (ClassFlag)
|
import Language.Java.Classfile.ClassFlag (ClassFlag)
|
||||||
import Language.Java.Classfile.ConstantPool.References (ClassReference)
|
import Language.Java.Classfile.ConstantPool.References (ClassReference)
|
||||||
import Language.Java.Classfile.Interfaces (Interfaces)
|
import Language.Java.Classfile.Interfaces (Interfaces)
|
||||||
|
import Language.Java.Classfile.Fields (Fields)
|
||||||
|
|
||||||
data Classfile = Classfile
|
data Classfile = Classfile
|
||||||
{ magic :: Magic
|
{ magic :: Magic
|
||||||
|
@ -19,6 +20,7 @@ data Classfile = Classfile
|
||||||
, this :: ClassReference
|
, this :: ClassReference
|
||||||
, super :: ClassReference
|
, super :: ClassReference
|
||||||
, interfaces :: Interfaces
|
, interfaces :: Interfaces
|
||||||
|
, fields :: Fields
|
||||||
}
|
}
|
||||||
deriving stock (Show, Generic)
|
deriving stock (Show, Generic)
|
||||||
deriving Extractable via Generically Classfile
|
deriving Extractable via Generically Classfile
|
||||||
|
|
21
src/Language/Java/Classfile/Attributes.hs
Normal file
21
src/Language/Java/Classfile/Attributes.hs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
|
{-# LANGUAGE DerivingVia #-}
|
||||||
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
|
module Language.Java.Classfile.Attributes (Attributes(..), Attribute(..)) where
|
||||||
|
import Data.Array.IArray (Array)
|
||||||
|
import Data.Word (Word16, Word32)
|
||||||
|
import Language.Java.Classfile.Extractable (Extractable)
|
||||||
|
import Language.Java.Classfile.ConstantPool.References (Utf8Reference)
|
||||||
|
import Language.Java.Classfile.Extractable.SizedBytes (SizedBytes)
|
||||||
|
import GHC.Generics ( Generic, Generically(..) )
|
||||||
|
|
||||||
|
newtype Attributes = Attributes (Array Word16 Attribute)
|
||||||
|
deriving stock (Show)
|
||||||
|
deriving newtype Extractable
|
||||||
|
|
||||||
|
data Attribute = Attribute
|
||||||
|
{ name :: Utf8Reference
|
||||||
|
, info :: SizedBytes Word32
|
||||||
|
}
|
||||||
|
deriving stock (Show, Generic)
|
||||||
|
deriving Extractable via Generically Attribute
|
|
@ -1,13 +1,15 @@
|
||||||
{-# LANGUAGE DerivingStrategies #-}
|
{-# LANGUAGE DerivingStrategies #-}
|
||||||
{-# LANGUAGE InstanceSigs #-}
|
{-# LANGUAGE InstanceSigs #-}
|
||||||
{-# LANGUAGE TypeApplications #-}
|
{-# LANGUAGE TypeApplications #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
module Language.Java.Classfile.ConstantPool (ConstantPool(..)) where
|
module Language.Java.Classfile.ConstantPool (ConstantPool(..)) where
|
||||||
import Data.Word (Word16)
|
import Data.Word (Word16)
|
||||||
import Data.Array.IArray (Array, listArray)
|
import Data.Array.IArray (Array, listArray)
|
||||||
import Language.Java.Classfile.ConstantPool.Entry (Entry)
|
import Language.Java.Classfile.ConstantPool.Entry (Entry, StorageCount (..), storageCount)
|
||||||
import Language.Java.Classfile.Extractable (Extractable (extract))
|
import Language.Java.Classfile.Extractable (Extractable (extract))
|
||||||
import Language.Java.Classfile.Extract (Extract, traceIndex)
|
import Language.Java.Classfile.Extract (Extract, traceIndex, traceType)
|
||||||
import Control.Monad (forM)
|
import Control.Monad (forM)
|
||||||
|
import qualified Data.Text as Text
|
||||||
|
|
||||||
newtype ConstantPool = ConstantPool (Array Word16 Entry)
|
newtype ConstantPool = ConstantPool (Array Word16 Entry)
|
||||||
deriving stock (Show)
|
deriving stock (Show)
|
||||||
|
@ -16,5 +18,21 @@ instance Extractable ConstantPool where
|
||||||
extract :: Extract ConstantPool
|
extract :: Extract ConstantPool
|
||||||
extract = do
|
extract = do
|
||||||
count <- extract @Word16
|
count <- extract @Word16
|
||||||
elements <- forM [1..fromIntegral count - 1] $ \ i -> traceIndex i extract
|
|
||||||
pure . ConstantPool $ listArray (1, count - 1) elements
|
let typeName = Text.concat
|
||||||
|
[ "ConstantPool ("
|
||||||
|
, Text.pack . show $ count
|
||||||
|
, ")"
|
||||||
|
]
|
||||||
|
|
||||||
|
let extractElements index end
|
||||||
|
| index == end = pure []
|
||||||
|
| otherwise = do
|
||||||
|
element <- traceIndex index extract
|
||||||
|
case storageCount element of
|
||||||
|
Once -> (element:) <$> extractElements (succ index) end
|
||||||
|
Twice -> ([element, element] <>) <$> extractElements (index + 2) end
|
||||||
|
|
||||||
|
traceType typeName $ do
|
||||||
|
elements <- extractElements 1 (fromIntegral count)
|
||||||
|
pure . ConstantPool $ listArray (1, count - 1) elements
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
{-# LANGUAGE TypeApplications #-}
|
{-# LANGUAGE TypeApplications #-}
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
{-# LANGUAGE InstanceSigs #-}
|
{-# LANGUAGE InstanceSigs #-}
|
||||||
module Language.Java.Classfile.ConstantPool.Entry (Entry(..)) where
|
{-# LANGUAGE LambdaCase #-}
|
||||||
|
{-# LANGUAGE OrPatterns #-}
|
||||||
|
module Language.Java.Classfile.ConstantPool.Entry (Entry(..), StorageCount(..), storageCount) where
|
||||||
import GHC.Generics (Generic, Generically(..))
|
import GHC.Generics (Generic, Generically(..))
|
||||||
import Language.Java.Classfile.Extractable (Extractable (extract))
|
import Language.Java.Classfile.Extractable (Extractable (extract))
|
||||||
import Language.Java.Classfile.Extractable.WithTag (Word8Tag)
|
import Language.Java.Classfile.Extractable.WithTag (Word8Tag)
|
||||||
|
@ -55,3 +57,11 @@ instance (Integral sizeType, Extractable sizeType) => Extractable (SizedText siz
|
||||||
Left err -> fail $ show err
|
Left err -> fail $ show err
|
||||||
Right t -> pure $ SizedText t
|
Right t -> pure $ SizedText t
|
||||||
|
|
||||||
|
data StorageCount = Once | Twice
|
||||||
|
|
||||||
|
storageCount :: Entry -> StorageCount
|
||||||
|
storageCount = \case
|
||||||
|
(Double _ ; Long _) -> Twice
|
||||||
|
_ -> Once
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -78,8 +78,8 @@ instance (Extractable index, Extractable element, Ix index, Integral index, Show
|
||||||
then pure $ listArray (1, 0) []
|
then pure $ listArray (1, 0) []
|
||||||
else traceType typeName $ do
|
else traceType typeName $ do
|
||||||
|
|
||||||
elements <- forM [0..fromIntegral count] $ \ i -> traceIndex i extract
|
elements <- forM [0..fromIntegral count - 1] $ \ i -> traceIndex i extract
|
||||||
pure $ listArray (1, count) elements
|
pure $ listArray (0, count - 1) elements
|
||||||
|
|
||||||
deriving via Generically () instance Extractable ()
|
deriving via Generically () instance Extractable ()
|
||||||
deriving via Generically (a, b) instance (Extractable a, Extractable b) => Extractable (a, b)
|
deriving via Generically (a, b) instance (Extractable a, Extractable b) => Extractable (a, b)
|
||||||
|
|
20
src/Language/Java/Classfile/Extractable/SizedBytes.hs
Normal file
20
src/Language/Java/Classfile/Extractable/SizedBytes.hs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{-# LANGUAGE DerivingStrategies #-}
|
||||||
|
{-# LANGUAGE InstanceSigs #-}
|
||||||
|
{-# LANGUAGE TypeApplications #-}
|
||||||
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
|
module Language.Java.Classfile.Extractable.SizedBytes (SizedBytes(..)) where
|
||||||
|
import Data.ByteString (ByteString)
|
||||||
|
import Language.Java.Classfile.Extractable (Extractable (..))
|
||||||
|
import Language.Java.Classfile.Extract (Extract, bytes)
|
||||||
|
import qualified Data.ByteString as StrictByteString
|
||||||
|
import qualified Data.ByteString.Lazy as ByteString
|
||||||
|
|
||||||
|
newtype SizedBytes sizeType = SizedBytes ByteString
|
||||||
|
deriving stock Show
|
||||||
|
|
||||||
|
instance (Extractable sizeType, Integral sizeType) => Extractable (SizedBytes sizeType) where
|
||||||
|
extract :: Extract (SizedBytes sizeType)
|
||||||
|
extract = do
|
||||||
|
size <- extract @sizeType
|
||||||
|
SizedBytes . StrictByteString.concat . ByteString.toChunks <$> bytes (fromIntegral size)
|
||||||
|
|
55
src/Language/Java/Classfile/Fields.hs
Normal file
55
src/Language/Java/Classfile/Fields.hs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
|
{-# LANGUAGE DerivingVia #-}
|
||||||
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
{-# LANGUAGE InstanceSigs #-}
|
||||||
|
{-# LANGUAGE LambdaCase #-}
|
||||||
|
module Language.Java.Classfile.Fields (Fields(..)) where
|
||||||
|
import Data.Array.IArray (Array)
|
||||||
|
import Data.Word (Word16)
|
||||||
|
import Language.Java.Classfile.Extractable (Extractable)
|
||||||
|
import GHC.Generics ( Generically, Generic, Generically(..) )
|
||||||
|
import Language.Java.Classfile.Flags (Flags)
|
||||||
|
import Language.Java.Classfile.Flag (FlagMask (..))
|
||||||
|
import Language.Java.Classfile.ConstantPool.References (Utf8Reference)
|
||||||
|
import Language.Java.Classfile.Attributes (Attributes)
|
||||||
|
|
||||||
|
newtype Fields = Fields (Array Word16 Field)
|
||||||
|
deriving stock Show
|
||||||
|
deriving newtype Extractable
|
||||||
|
|
||||||
|
data FieldFlag
|
||||||
|
= Public
|
||||||
|
| Private
|
||||||
|
| Protected
|
||||||
|
| Static
|
||||||
|
| Final
|
||||||
|
| Volatile
|
||||||
|
| Transient
|
||||||
|
| Synthetic
|
||||||
|
| Enumeration -- original "Enum"
|
||||||
|
deriving stock (Show, Eq, Ord, Enum, Bounded)
|
||||||
|
|
||||||
|
instance FlagMask FieldFlag where
|
||||||
|
type FlagType FieldFlag = Word16
|
||||||
|
maskOf :: FieldFlag -> FlagType FieldFlag
|
||||||
|
maskOf = \case
|
||||||
|
Public -> 0x0001
|
||||||
|
Private -> 0x0002
|
||||||
|
Protected -> 0x0004
|
||||||
|
Static -> 0x0008
|
||||||
|
Final -> 0x0010
|
||||||
|
Volatile -> 0x0040
|
||||||
|
Transient -> 0x0080
|
||||||
|
Synthetic -> 0x1000
|
||||||
|
Enumeration -> 0x4000
|
||||||
|
|
||||||
|
|
||||||
|
data Field = Field
|
||||||
|
{ flags :: Flags FieldFlag
|
||||||
|
, name :: Utf8Reference
|
||||||
|
, descriptor :: Utf8Reference
|
||||||
|
, attribute :: Attributes
|
||||||
|
}
|
||||||
|
deriving stock (Show, Generic)
|
||||||
|
deriving Extractable via Generically Field
|
Loading…
Add table
Add a link
Reference in a new issue