Compare commits

..

8 commits

21 changed files with 148 additions and 62 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "3rdparty/pretty-parse"]
path = 3rdparty/pretty-parse
url = https://git.jossco.de/vegowotenks/pretty-parse

1
3rdparty/pretty-parse vendored Submodule

@ -0,0 +1 @@
Subproject commit a7bff630fc3e5e140274fb65d6b88b46e7a086eb

View file

@ -4,6 +4,8 @@
module Main (main) where module Main (main) where
import Data.ByteString.Lazy qualified as ByteString import Data.ByteString.Lazy qualified as ByteString
import Data.Text.Lazy.IO qualified as LazyTextIO
import Pretty.Serialize qualified as Pretty
import Language.Java.Classfile (Classfile) import Language.Java.Classfile (Classfile)
import Language.Java.Classfile.Extract (runExtract) import Language.Java.Classfile.Extract (runExtract)
@ -13,4 +15,4 @@ import Language.Java.Classfile.Stage (Stage(Parse))
main :: IO () main :: IO ()
main = do main = do
input <- ByteString.getContents input <- ByteString.getContents
print $ runExtract input (extract @(Classfile Parse)) LazyTextIO.putStrLn . Pretty.serialize $ runExtract input (extract @(Classfile Parse))

View file

@ -44,12 +44,13 @@ library
Paths_java_classfile Paths_java_classfile
hs-source-dirs: hs-source-dirs:
src src
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -Wunused-packages
build-depends: build-depends:
array array
, base >=4.7 && <5 , base >=4.7 && <5
, bytestring , bytestring
, containers , containers
, pretty-parse
, text , text
default-language: Haskell2010 default-language: Haskell2010
@ -59,13 +60,12 @@ executable java-classfile-exe
Paths_java_classfile Paths_java_classfile
hs-source-dirs: hs-source-dirs:
app app
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -Wunused-packages -threaded -rtsopts -with-rtsopts=-N
build-depends: build-depends:
array base >=4.7 && <5
, base >=4.7 && <5
, bytestring , bytestring
, containers
, java-classfile , java-classfile
, pretty-parse
, text , text
default-language: Haskell2010 default-language: Haskell2010
@ -76,12 +76,9 @@ test-suite java-classfile-test
Paths_java_classfile Paths_java_classfile
hs-source-dirs: hs-source-dirs:
test test
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -Wunused-packages -threaded -rtsopts -with-rtsopts=-N
build-depends: build-depends:
array base >=4.7 && <5
, base >=4.7 && <5
, bytestring , bytestring
, containers
, java-classfile , java-classfile
, text
default-language: Haskell2010 default-language: Haskell2010

View file

@ -19,11 +19,8 @@ synopsis: Multi-Stage classfile parsing and verification.
description: Please see the README on Forgejo at <https://git.jossco.de/vegowotenks/java-classfile#readme> description: Please see the README on Forgejo at <https://git.jossco.de/vegowotenks/java-classfile#readme>
dependencies: dependencies:
- array
- base >= 4.7 && < 5 - base >= 4.7 && < 5
- bytestring - bytestring
- containers
- text
ghc-options: ghc-options:
- -Wall - -Wall
@ -35,9 +32,15 @@ ghc-options:
- -Wmissing-home-modules - -Wmissing-home-modules
- -Wpartial-fields - -Wpartial-fields
- -Wredundant-constraints - -Wredundant-constraints
- -Wunused-packages
library: library:
source-dirs: src source-dirs: src
dependencies:
- array
- containers
- pretty-parse
- text
executables: executables:
java-classfile-exe: java-classfile-exe:
@ -49,6 +52,8 @@ executables:
- -with-rtsopts=-N - -with-rtsopts=-N
dependencies: dependencies:
- java-classfile - java-classfile
- pretty-parse
- text
tests: tests:
java-classfile-test: java-classfile-test:

View file

@ -11,6 +11,7 @@
{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Language.Java.Classfile (Classfile(..)) where module Language.Java.Classfile (Classfile(..)) where
import GHC.Generics (Generic, Generically(Generically)) import GHC.Generics (Generic, Generically(Generically))
@ -29,6 +30,7 @@ import Language.Java.Classfile.Fields (Fields)
import Language.Java.Classfile.Methods (Methods) import Language.Java.Classfile.Methods (Methods)
import Language.Java.Classfile.Attributes (Attributes) import Language.Java.Classfile.Attributes (Attributes)
import Data.Word (Word16) import Data.Word (Word16)
import Pretty.Serialize (PrettySerialize)
-- | 'Stage'-indexed classfile. It can represent a class, an interface or a module. -- | 'Stage'-indexed classfile. It can represent a class, an interface or a module.
@ -50,6 +52,7 @@ data Classfile stage = Classfile
deriving instance (Show (Magic stage), Show (ConstantPool stage), Show (ClassFlags stage), Show (Class stage)) => Show (Classfile stage) deriving instance (Show (Magic stage), Show (ConstantPool stage), Show (ClassFlags stage), Show (Class stage)) => Show (Classfile stage)
deriving via Generically (Classfile Parse) instance (Extractable (Classfile Parse)) deriving via Generically (Classfile Parse) instance (Extractable (Classfile Parse))
deriving via Generically (Classfile Parse) instance (PrettySerialize (Classfile Parse))
type ClassFlags :: Stage -> Type type ClassFlags :: Stage -> Type
data family ClassFlags stage data family ClassFlags stage
@ -57,18 +60,20 @@ data family ClassFlags stage
newtype instance ClassFlags Parse = ClassFlags (Flags ClassFlag) newtype instance ClassFlags Parse = ClassFlags (Flags ClassFlag)
deriving stock (Show, Generic) deriving stock (Show, Generic)
deriving Extractable via Generically (ClassFlags Parse) deriving Extractable via Generically (ClassFlags Parse)
deriving newtype PrettySerialize
data ClassFlag data ClassFlag
= Public = Public -- ^ may be accessed from outside the package
| Final | Final -- ^ no subclasses allowed
| Super | Super -- ^ treat superclass methods special when using InvokeSpecial
| Interface | Interface -- ^ is an interface
| Abstract | Abstract -- ^ abstract, must not be instantiated
| Synthetic | Synthetic -- ^ not present in source code
| Annotation | Annotation -- ^ is annotation interface
| Enum | Enum -- ^ enumerated instances
| Module | Module -- ^ module, not a class
deriving (Show, Eq, Ord, Enum, Bounded) deriving (Show, Eq, Ord, Enum, Bounded, Generic)
deriving PrettySerialize via Generically ClassFlag
instance FlagMask ClassFlag where instance FlagMask ClassFlag where
type FlagType ClassFlag = Word16 type FlagType ClassFlag = Word16

View file

@ -10,6 +10,7 @@ import Language.Java.Classfile.Extractable (Extractable)
import Language.Java.Classfile.ConstantPool.References (Utf8Reference) import Language.Java.Classfile.ConstantPool.References (Utf8Reference)
import Language.Java.Classfile.Extractable.SizedBytes (SizedBytes) import Language.Java.Classfile.Extractable.SizedBytes (SizedBytes)
import GHC.Generics ( Generic, Generically(..) ) import GHC.Generics ( Generic, Generically(..) )
import Pretty.Serialize (PrettySerialize)
-- | Generic Attribute array used everywhere. -- | Generic Attribute array used everywhere.
-- --
@ -17,7 +18,7 @@ import GHC.Generics ( Generic, Generically(..) )
newtype Attributes = Attributes (Array Word16 Attribute) newtype Attributes = Attributes (Array Word16 Attribute)
deriving stock (Show) deriving stock (Show)
deriving newtype Extractable deriving newtype (Extractable, PrettySerialize)
-- | Unknown Attribute -- | Unknown Attribute
@ -26,4 +27,4 @@ data Attribute = Attribute
, info :: SizedBytes Word32 , info :: SizedBytes Word32
} }
deriving stock (Show, Generic) deriving stock (Show, Generic)
deriving Extractable via Generically Attribute deriving (Extractable, PrettySerialize) via Generically Attribute

View file

@ -1,6 +1,5 @@
-- | THE constant pool, all the constants in a class file are handled in here. -- | THE constant pool, all the constants in a class file are handled in here.
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeApplications #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
@ -10,6 +9,8 @@
{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-} {-# LANGUAGE GADTs #-}
{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE DeriveGeneric #-}
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)
@ -19,13 +20,19 @@ import Language.Java.Classfile.Extract (Extract, traceIndex, traceType)
import qualified Data.Text as Text import qualified Data.Text as Text
import Language.Java.Classfile.Stage (Stage(..)) import Language.Java.Classfile.Stage (Stage(..))
import Data.Kind (Type) import Data.Kind (Type)
import GHC.Generics (Generically(..), Generic)
import Pretty.Serialize (PrettySerialize)
type ConstantPool :: Stage -> Type type ConstantPool :: Stage -> Type
data ConstantPool stage where data family ConstantPool stage
ConstantPool :: (Array Word16 Entry) -> ConstantPool Parse
NoPool :: ConstantPool Resolve newtype instance ConstantPool Parse = ConstantPool (Array Word16 Entry)
deriving stock (Generic, Show)
deriving via (Generically (ConstantPool Parse)) instance PrettySerialize (ConstantPool Parse)
data instance ConstantPool Resolve = NoPool
deriving instance Show (ConstantPool stage)
-- | 'Stage'-indexed constant-pool. The constant-pool is erased after resolving the class file. -- | 'Stage'-indexed constant-pool. The constant-pool is erased after resolving the class file.

View file

@ -8,6 +8,7 @@
{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OrPatterns #-} {-# LANGUAGE OrPatterns #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Language.Java.Classfile.ConstantPool.Entry (Entry(..), StorageCount(..), storageCount, MethodHandleInfo(..)) where module Language.Java.Classfile.ConstantPool.Entry (Entry(..), StorageCount(..), storageCount, MethodHandleInfo(..)) 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))
@ -20,6 +21,7 @@ import Language.Java.Classfile.Extract (Extract, bytes)
import qualified Data.Text.Encoding as Text import qualified Data.Text.Encoding as Text
import qualified Data.ByteString.Lazy as ByteString import qualified Data.ByteString.Lazy as ByteString
import qualified Data.ByteString as StrictByteString import qualified Data.ByteString as StrictByteString
import Pretty.Serialize (PrettySerialize)
-- | A single entry. Double and Long are not followed by something unusable, they are duplicated instead. -- | A single entry. Double and Long are not followed by something unusable, they are duplicated instead.
@ -60,6 +62,7 @@ data Entry
-- ^ Some package description -- ^ Some package description
deriving stock (Show, Generic) deriving stock (Show, Generic)
deriving Extractable via Generically Entry deriving Extractable via Generically Entry
deriving PrettySerialize via Generically Entry
-- | Holds the invariants of MethodHandles (Only certain references are allowed after some kinds) -- | Holds the invariants of MethodHandles (Only certain references are allowed after some kinds)
-- --
@ -68,11 +71,13 @@ data Entry
data MethodHandleInfo = MethodHandleInfo MethodHandleReferenceKind OpaqueReference data MethodHandleInfo = MethodHandleInfo MethodHandleReferenceKind OpaqueReference
deriving stock (Show, Generic) deriving stock (Show, Generic)
deriving Extractable via Generically MethodHandleInfo deriving Extractable via Generically MethodHandleInfo
deriving PrettySerialize via Generically MethodHandleInfo
-- | Extractor newtype for a java-utf-text with size tag specified as a type argument. -- | Extractor newtype for a java-utf-text with size tag specified as a type argument.
newtype SizedText sizeType = SizedText Text newtype SizedText sizeType = SizedText Text
deriving stock (Show) deriving stock (Show)
deriving newtype PrettySerialize
instance (Integral sizeType, Extractable sizeType) => Extractable (SizedText sizeType) where instance (Integral sizeType, Extractable sizeType) => Extractable (SizedText sizeType) where
extract :: Extract (SizedText sizeType) extract :: Extract (SizedText sizeType)

View file

@ -7,6 +7,7 @@
{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
{-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE DeriveGeneric #-}
module Language.Java.Classfile.ConstantPool.References (Utf8Reference(..), ClassReference(..), NameAndTypeReference(..), MethodHandleReferenceKind(..), OpaqueReference(..), BootstrapMethodIndex(..), Class) where module Language.Java.Classfile.ConstantPool.References (Utf8Reference(..), ClassReference(..), NameAndTypeReference(..), MethodHandleReferenceKind(..), OpaqueReference(..), BootstrapMethodIndex(..), Class) where
import Data.Word (Word16, Word8) import Data.Word (Word16, Word8)
import Language.Java.Classfile.Extractable (Extractable) import Language.Java.Classfile.Extractable (Extractable)
@ -14,12 +15,15 @@ import Language.Java.Classfile.Extractable.AsTag
( TagValue(..), AsTag, AsTag(..) ) ( TagValue(..), AsTag, AsTag(..) )
import Language.Java.Classfile.Stage (Stage(..)) import Language.Java.Classfile.Stage (Stage(..))
import Data.Kind (Type) import Data.Kind (Type)
import Pretty.Serialize (PrettySerialize)
import GHC.Generics (Generically(..), Generic)
-- | Wrapper for constant-pool reference to text. -- | Wrapper for constant-pool reference to text.
newtype Utf8Reference = Utf8Reference Word16 newtype Utf8Reference = Utf8Reference Word16
deriving stock (Show) deriving stock (Show, Generic)
deriving newtype Extractable deriving newtype Extractable
deriving PrettySerialize via Generically Utf8Reference
-- | 'Stage'-indexed type, either a Class or only a t'ClassReference'. -- | 'Stage'-indexed type, either a Class or only a t'ClassReference'.
@ -30,26 +34,30 @@ type family Class stage where
-- | Reference to a class in a constant-pool. This will resolve into a class. -- | Reference to a class in a constant-pool. This will resolve into a class.
newtype ClassReference = ClassReference Word16 newtype ClassReference = ClassReference Word16
deriving stock (Show) deriving stock (Show, Generic)
deriving newtype Extractable deriving newtype Extractable
deriving PrettySerialize via Generically ClassReference
-- | Reference to a class in a constant-pool. This will resolve to Name and Type. -- | Reference to a class in a constant-pool. This will resolve to Name and Type.
newtype NameAndTypeReference = NameAndTypeReference Word16 newtype NameAndTypeReference = NameAndTypeReference Word16
deriving stock (Show) deriving stock (Show, Generic)
deriving newtype Extractable deriving newtype Extractable
deriving PrettySerialize via Generically NameAndTypeReference
-- | Reference to something in a constant-pool. I will hopefully get rid of this type. -- | Reference to something in a constant-pool. I will hopefully get rid of this type.
newtype OpaqueReference = OpaqueReference Word16 newtype OpaqueReference = OpaqueReference Word16
deriving stock (Show) deriving stock (Show, Generic)
deriving newtype Extractable deriving newtype Extractable
deriving PrettySerialize via Generically OpaqueReference
-- | Reference to a method in the BootstrapMethods class attribute -- | Reference to a method in the BootstrapMethods class attribute
newtype BootstrapMethodIndex = BootstrapMethodIndex Word16 newtype BootstrapMethodIndex = BootstrapMethodIndex Word16
deriving stock (Show) deriving stock (Show, Generic)
deriving newtype Extractable deriving newtype Extractable
deriving PrettySerialize via Generically BootstrapMethodIndex
-- | A Tag used to determine the type of a MethodHandle -- | A Tag used to determine the type of a MethodHandle
@ -63,8 +71,9 @@ data MethodHandleReferenceKind
| InvokeSpecial | InvokeSpecial
| NewInvokeSpecial | NewInvokeSpecial
| InvokeInterface | InvokeInterface
deriving stock (Show, Enum, Bounded) deriving stock (Show, Enum, Bounded, Generic)
deriving Extractable via AsTag MethodHandleReferenceKind deriving Extractable via AsTag MethodHandleReferenceKind
deriving PrettySerialize via Generically MethodHandleReferenceKind
instance TagValue MethodHandleReferenceKind where instance TagValue MethodHandleReferenceKind where
type TagType MethodHandleReferenceKind = Word8 type TagType MethodHandleReferenceKind = Word8

View file

@ -2,19 +2,30 @@
{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE DeriveGeneric #-}
module Language.Java.Classfile.Extract (Extract(), bytes, runExtract, expectRaw, expectEqual, traceType, traceConstructor, traceField, traceIndex, Reason(..), Trace(..), Expected(..), Actual(..), TypeName(..)) where module Language.Java.Classfile.Extract (Extract(), bytes, runExtract, expectRaw, expectEqual, traceType, traceConstructor, traceField, traceIndex, Reason(..), Trace(..), Expected(..), Actual(..), TypeName(..)) where
import Data.ByteString.Lazy (ByteString)
import qualified Data.ByteString.Lazy as ByteString
import Control.Applicative (Alternative (empty, (<|>))) import Control.Applicative (Alternative (empty, (<|>)))
import Control.Monad (MonadPlus)
import GHC.Generics (Generic, Generically(..))
import Data.ByteString.Lazy (ByteString)
import Data.Text (Text) import Data.Text (Text)
import qualified Data.Text as Text
import Data.Typeable (Typeable, typeOf) import Data.Typeable (Typeable, typeOf)
import Pretty.Serialize (PrettySerialize)
import qualified Data.ByteString.Lazy as ByteString
import qualified Data.Text as Text
-- | Extractor Monad. Computations running in this monad will automatically keep track of used resources and backtrack arbitrarily. -- | Extractor Monad. Computations running in this monad will automatically keep track of used resources and backtrack arbitrarily.
newtype Extract a = Extract (Continuation a) newtype Extract a = Extract (Continuation a)
deriving (Functor) deriving (Functor)
deriving anyclass MonadPlus
-- | Functions work wonders when defining monads. -- | Functions work wonders when defining monads.
@ -29,15 +40,18 @@ data Reply a
-- | Type Alias for the Show instance -- | Type Alias for the Show instance
newtype Expected = Expected Text newtype Expected = Expected Text
deriving Show deriving stock (Show, Generic)
deriving PrettySerialize via Generically Expected
-- | Type Alias for the Show instance -- | Type Alias for the Show instance
newtype Actual = Actual Text newtype Actual = Actual Text
deriving Show deriving stock (Show, Generic)
deriving PrettySerialize via Generically Actual
-- | Type Alias for the Show instance -- | Type Alias for the Show instance
newtype TypeName = TypeName Text newtype TypeName = TypeName Text
deriving Show deriving stock (Show, Generic)
deriving PrettySerialize via Generically TypeName
-- | Why did the computation fail? -- | Why did the computation fail?
@ -50,7 +64,8 @@ data Reason
-- ^ Something else went wrong -- ^ Something else went wrong
| Unknown | Unknown
-- ^ Someone used the 'empty' function from 'Alternative' -- ^ Someone used the 'empty' function from 'Alternative'
deriving Show deriving stock (Show, Generic)
deriving PrettySerialize via Generically Reason
-- | Where did the computation fail? Calls to these functions are auto-generated by the Generic instances. -- | Where did the computation fail? Calls to these functions are auto-generated by the Generic instances.
@ -59,7 +74,8 @@ data Trace
| InConstructor Text | InConstructor Text
| InField Text | InField Text
| AtIndex Word | AtIndex Word
deriving Show deriving stock (Show, Generic)
deriving PrettySerialize via Generically Trace
instance Applicative Extract where instance Applicative Extract where
-- | Don't consume any input -- | Don't consume any input

View file

@ -1,20 +1,22 @@
-- | Read arbitrary bytes prefixed with a length. -- | Read arbitrary bytes prefixed with a length.
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE DerivingVia #-}
module Language.Java.Classfile.Extractable.SizedBytes (SizedBytes(..)) where module Language.Java.Classfile.Extractable.SizedBytes (SizedBytes(..)) where
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
import Language.Java.Classfile.Extractable (Extractable (..)) import Language.Java.Classfile.Extractable (Extractable (..))
import Language.Java.Classfile.Extract (Extract, bytes) import Language.Java.Classfile.Extract (Extract, bytes)
import qualified Data.ByteString as StrictByteString import qualified Data.ByteString as StrictByteString
import qualified Data.ByteString.Lazy as ByteString import qualified Data.ByteString.Lazy as ByteString
import Pretty.Serialize (PrettySerialize, ShowPrettySerialize(..))
-- | The sizeType type Paramter is used to extract the correct byte count. -- | The sizeType type Paramter is used to extract the correct byte count.
newtype SizedBytes sizeType = SizedBytes ByteString newtype SizedBytes sizeType = SizedBytes ByteString
deriving stock Show deriving stock Show
deriving PrettySerialize via ShowPrettySerialize (SizedBytes sizeType)
instance (Extractable sizeType, Integral sizeType) => Extractable (SizedBytes sizeType) where instance (Extractable sizeType, Integral sizeType) => Extractable (SizedBytes sizeType) where
extract :: Extract (SizedBytes sizeType) extract :: Extract (SizedBytes sizeType)

View file

@ -16,6 +16,7 @@ import Control.Monad (void)
import Data.Proxy (Proxy(Proxy)) import Data.Proxy (Proxy(Proxy))
import Data.Typeable ( Typeable ) import Data.Typeable ( Typeable )
import Data.Word (Word8) import Data.Word (Word8)
import Pretty.Serialize (PrettySerialize)
-- | Type alias if you use the same type a lot. -- | Type alias if you use the same type a lot.
@ -25,7 +26,7 @@ type Word8Tag value a = WithNumericTag value Word8 a
type WithNumericTag :: Natural -> Type -> Type -> Type type WithNumericTag :: Natural -> Type -> Type -> Type
newtype WithNumericTag value tagType a = Tagged a newtype WithNumericTag value tagType a = Tagged a
deriving newtype Show deriving newtype (Show, PrettySerialize)
instance (KnownNat value, Extractable a, Extractable tagType, Eq tagType, Num tagType, Show tagType, Typeable tagType) => Extractable (WithNumericTag value tagType a) where instance (KnownNat value, Extractable a, Extractable tagType, Eq tagType, Num tagType, Show tagType, Typeable tagType) => Extractable (WithNumericTag value tagType a) where
extract :: Extract (WithNumericTag value tagType a) extract :: Extract (WithNumericTag value tagType a)

View file

@ -14,12 +14,13 @@ import GHC.Generics ( Generically, Generic, Generically(..) )
import Language.Java.Classfile.Flags (Flags, FlagMask (..)) import Language.Java.Classfile.Flags (Flags, FlagMask (..))
import Language.Java.Classfile.ConstantPool.References (Utf8Reference) import Language.Java.Classfile.ConstantPool.References (Utf8Reference)
import Language.Java.Classfile.Attributes (Attributes) import Language.Java.Classfile.Attributes (Attributes)
import Pretty.Serialize (PrettySerialize)
-- | Word16-Array of Fields. -- | Word16-Array of Fields.
newtype Fields = Fields (Array Word16 Field) newtype Fields = Fields (Array Word16 Field)
deriving stock Show deriving stock Show
deriving newtype Extractable deriving newtype (Extractable, PrettySerialize)
-- | All the access flags a field can have -- | All the access flags a field can have
@ -33,7 +34,8 @@ data FieldFlag
| Transient | Transient
| Synthetic | Synthetic
| Enumeration -- original "Enum" | Enumeration -- original "Enum"
deriving stock (Show, Eq, Ord, Enum, Bounded) deriving stock (Show, Eq, Ord, Enum, Bounded, Generic)
deriving PrettySerialize via Generically FieldFlag
instance FlagMask FieldFlag where instance FlagMask FieldFlag where
type FlagType FieldFlag = Word16 type FlagType FieldFlag = Word16
@ -58,4 +60,4 @@ data Field = Field
, attribute :: Attributes , attribute :: Attributes
} }
deriving stock (Show, Generic) deriving stock (Show, Generic)
deriving Extractable via Generically Field deriving (Extractable, PrettySerialize) via Generically Field

View file

@ -6,10 +6,13 @@
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeFamilies #-}
module Language.Java.Classfile.Flags (Flags(..), FlagMask(..)) where {-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Language.Java.Classfile.Flags (Flags(..), FlagMask(..), containsFlag) where
import Data.Bits (Bits((.&.))) import Data.Bits (Bits((.&.), zeroBits))
import Data.Enum.Util (enumerate) import Data.Enum.Util (enumerate)
import Data.Set (Set) import Data.Set (Set)
@ -18,11 +21,15 @@ import qualified Data.Set as Set
import Language.Java.Classfile.Extract (Extract) import Language.Java.Classfile.Extract (Extract)
import Language.Java.Classfile.Extractable (Extractable (extract)) import Language.Java.Classfile.Extractable (Extractable (extract))
import Data.Kind (Type) import Data.Kind (Type)
import Control.Arrow ((>>>))
import qualified Data.List as List
import Pretty.Serialize (PrettySerialize)
-- | Using the 'FlagMask' instance of the type parameter, this will extract all the flags whose mask produced a non-zero value using '.&.' -- | Using the 'FlagMask' instance of the type parameter, this will extract all the flags whose mask produced a non-zero value using '.&.'
newtype Flags a = Flags (Set a) newtype Flags a = Flags (Set a)
deriving (Show) deriving (Show)
deriving newtype PrettySerialize
instance (Extractable (FlagType a), Bounded a, Enum a, Ord a, FlagMask a, Bits (FlagType a), Num (FlagType a)) => Extractable (Flags a) where instance (Extractable (FlagType a), Bounded a, Enum a, Ord a, FlagMask a, Bits (FlagType a), Num (FlagType a)) => Extractable (Flags a) where
extract :: Extract (Flags a) extract :: Extract (Flags a)
@ -39,3 +46,13 @@ class FlagMask a where
type FlagType a :: Type type FlagType a :: Type
maskOf :: a -> FlagType a maskOf :: a -> FlagType a
ofMask :: FlagType a -> Set a
default ofMask :: (Enum a, Bounded a, Ord a, Bits (FlagType a)) => FlagType a -> Set a
ofMask mask = List.filter (containsFlag mask)
>>> Set.fromList
$ enumerate @a
containsFlag :: (Bits (FlagType a), FlagMask a) => FlagType a -> a -> Bool
containsFlag mask flag = mask .&. maskOf flag /= zeroBits

View file

@ -8,9 +8,10 @@ import Data.Word (Word16)
import Language.Java.Classfile.ConstantPool.References (ClassReference) import Language.Java.Classfile.ConstantPool.References (ClassReference)
import Language.Java.Classfile.Extractable (Extractable) import Language.Java.Classfile.Extractable (Extractable)
import GHC.Generics ( Generic, Generically, Generically(..) ) import GHC.Generics ( Generic, Generically, Generically(..) )
import Pretty.Serialize (PrettySerialize)
-- | A list of classes something implements. -- | A list of classes something implements.
newtype Interfaces = Interfaces (Array Word16 ClassReference) newtype Interfaces = Interfaces (Array Word16 ClassReference)
deriving stock (Show, Generic) deriving stock (Show, Generic)
deriving Extractable via Generically Interfaces deriving (Extractable, PrettySerialize) via Generically Interfaces

View file

@ -6,6 +6,8 @@
{-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-} {-# LANGUAGE GADTs #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DerivingVia #-}
module Language.Java.Classfile.Magic (Magic(..)) where module Language.Java.Classfile.Magic (Magic(..)) where
import Data.Word (Word32) import Data.Word (Word32)
import Language.Java.Classfile.Extractable (Extractable, extract, expectConstant) import Language.Java.Classfile.Extractable (Extractable, extract, expectConstant)
@ -13,6 +15,7 @@ import Language.Java.Classfile.Extract (Extract)
import Data.Hex (Hex (Hex)) import Data.Hex (Hex (Hex))
import Language.Java.Classfile.Stage (Stage(Parse, Resolve)) import Language.Java.Classfile.Stage (Stage(Parse, Resolve))
import Data.Kind (Type) import Data.Kind (Type)
import Pretty.Serialize (ShowPrettySerialize(ShowPrettySerialize), PrettySerialize)
-- | 'Stage'-indexed Magic type. The 'Resolve' stage is only a unit type. -- | 'Stage'-indexed Magic type. The 'Resolve' stage is only a unit type.
@ -21,6 +24,9 @@ data Magic stage where
Magic :: Hex Word32 -> Magic Parse Magic :: Hex Word32 -> Magic Parse
Cafebabe :: Magic Resolve Cafebabe :: Magic Resolve
deriving instance Show (Magic stage)
deriving via ShowPrettySerialize (Magic stage) instance PrettySerialize (Magic stage)
instance Extractable (Magic Parse) where instance Extractable (Magic Parse) where
extract :: Extract (Magic Parse) extract :: Extract (Magic Parse)
extract = Magic . Hex <$> expectConstant 0xCAFEBABE extract = Magic . Hex <$> expectConstant 0xCAFEBABE

View file

@ -14,12 +14,13 @@ import Language.Java.Classfile.Extractable (Extractable)
import GHC.Generics ( Generically, Generic, Generically(..) ) import GHC.Generics ( Generically, Generic, Generically(..) )
import Language.Java.Classfile.ConstantPool.References (Utf8Reference) import Language.Java.Classfile.ConstantPool.References (Utf8Reference)
import Language.Java.Classfile.Attributes (Attributes) import Language.Java.Classfile.Attributes (Attributes)
import Pretty.Serialize (PrettySerialize)
-- | Alias for the methods structure from the constant-pool. -- | Alias for the methods structure from the constant-pool.
newtype Methods = Methods (Array Word16 Method) newtype Methods = Methods (Array Word16 Method)
deriving stock (Show) deriving stock (Show)
deriving newtype Extractable deriving newtype (Extractable, PrettySerialize)
-- | A single method record, contains attributes, name and access flags. -- | A single method record, contains attributes, name and access flags.
@ -30,7 +31,7 @@ data Method = Method
, attributes :: Attributes , attributes :: Attributes
} }
deriving stock (Show, Generic) deriving stock (Show, Generic)
deriving Extractable via Generically Method deriving (Extractable, PrettySerialize) via Generically Method
-- | Flags for the method, such as abstract, public or static. -- | Flags for the method, such as abstract, public or static.
@ -47,7 +48,8 @@ data MethodFlag
| Abstract | Abstract
| Strict | Strict
| Synthetic | Synthetic
deriving stock (Show, Eq, Ord, Enum, Bounded) deriving stock (Show, Eq, Ord, Enum, Bounded, Generic)
deriving PrettySerialize via Generically MethodFlag
instance FlagMask MethodFlag where instance FlagMask MethodFlag where
type FlagType MethodFlag = Word16 type FlagType MethodFlag = Word16

View file

@ -7,6 +7,7 @@ module Language.Java.Classfile.Version (Version(..)) where
import Data.Word (Word16) import Data.Word (Word16)
import GHC.Generics (Generic, Generically(Generically)) import GHC.Generics (Generic, Generically(Generically))
import Language.Java.Classfile.Extractable (Extractable) import Language.Java.Classfile.Extractable (Extractable)
import Pretty.Serialize (PrettySerialize)
-- | Classfile versions only have two components. The minor component is zero since some java version. -- | Classfile versions only have two components. The minor component is zero since some java version.
@ -15,7 +16,7 @@ data Version = Version
, major :: Word16 , major :: Word16
} }
deriving stock (Show, Generic) deriving stock (Show, Generic)
deriving Extractable via Generically Version deriving (Extractable, PrettySerialize) via Generically Version
-- >>> import Language.Java.Classfile.Extractable (Extractable(extract)) -- >>> import Language.Java.Classfile.Extractable (Extractable(extract))
-- >>> import Language.Java.Classfile.Extract (runExtract, Extract) -- >>> import Language.Java.Classfile.Extract (runExtract, Extract)

View file

@ -17,7 +17,8 @@
# #
# snapshot: ./custom-snapshot.yaml # snapshot: ./custom-snapshot.yaml
# snapshot: https://example.com/snapshots/2024-01-01.yaml # snapshot: https://example.com/snapshots/2024-01-01.yaml
snapshot: nightly-2025-07-10 snapshot:
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/24/3.yaml
compiler: ghc-9.12.1 compiler: ghc-9.12.1
# User packages to be built. # User packages to be built.
@ -31,6 +32,7 @@ compiler: ghc-9.12.1
# - wai # - wai
packages: packages:
- . - .
- 3rdparty/pretty-parse
# Dependency packages to be pulled from upstream that are not in the snapshot. # Dependency packages to be pulled from upstream that are not in the snapshot.
# These entries can reference officially published versions as well as # These entries can reference officially published versions as well as
# forks / in-progress versions pinned to a git hash. For example: # forks / in-progress versions pinned to a git hash. For example:

View file

@ -6,7 +6,8 @@
packages: [] packages: []
snapshots: snapshots:
- completed: - completed:
sha256: 39e3a4dc79edf153bb0aa6dc4206b1543c0e0f3e3811ec751abdcdf3aaf08887 sha256: aa97dce5253937e4aa56100a0a9dc1f79a554cf543ad7cfab0afe6ed42de2f31
size: 723871 size: 724941
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/nightly/2025/7/10.yaml url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/24/3.yaml
original: nightly-2025-07-10 original:
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/24/3.yaml