{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE RecordWildCards #-}

module JVM.Data.Raw.ClassFile where

import Data.Binary.Builder (toLazyByteString)
import Data.Binary.Put
import Data.Binary.Write (WriteBinary (writeBinary), writeList)
import Data.ByteString qualified as B
import Data.Vector (Vector)
import Data.Vector qualified as V
import Data.Word
import JVM.Data.JVMVersion (MajorVersion (..), MinorVersion, unwrapMajor, unwrapMinor)
import JVM.Data.Raw.ConstantPool (ConstantPoolInfo)
import JVM.Data.Raw.Instruction (Instruction)
import JVM.Data.Raw.MagicNumbers qualified as MagicNumbers
import JVM.Data.Raw.Types

{-
ClassFile {
    u4             magic;
    u2             minor_version;
    u2             major_version;
    u2             constant_pool_count;
    cp_info        constant_pool[constant_pool_count-1];
    u2             access_flags;
    u2             this_class;
    u2             super_class;
    u2             interfaces_count;
    u2             interfaces[interfaces_count];
    u2             fields_count;
    field_info     fields[fields_count];
    u2             methods_count;
    method_info    methods[methods_count];
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}
-}

{- | Low level representation of the class file format.
This is the closest representation to the actual format of the class file, that makes only a few compromises for convenience,
such as omitting the explicit x_count fields, instead calculating them from the length of the corresponding vectors.
This has the added bonus of making it impossible to construct an invalid class file (in this regard anyway)
-}
data ClassFile = ClassFile
    { ClassFile -> Word32
magic :: Word32
    , ClassFile -> MinorVersion
minorVersion :: MinorVersion
    , ClassFile -> MajorVersion
majorVersion :: MajorVersion
    , ClassFile -> Vector ConstantPoolInfo
constantPool :: Vector ConstantPoolInfo
    , ClassFile -> Word16
accessFlags :: Word16
    , ClassFile -> Word16
thisClass :: Word16
    , ClassFile -> Word16
superClass :: Word16
    , ClassFile -> Vector Word16
interfaces :: Vector Word16
    , ClassFile -> Vector FieldInfo
fields :: Vector FieldInfo
    , ClassFile -> Vector MethodInfo
methods :: Vector MethodInfo
    , ClassFile -> Vector AttributeInfo
attributes :: Vector AttributeInfo
    }
    deriving (Int -> ClassFile -> ShowS
[ClassFile] -> ShowS
ClassFile -> String
(Int -> ClassFile -> ShowS)
-> (ClassFile -> String)
-> ([ClassFile] -> ShowS)
-> Show ClassFile
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ClassFile -> ShowS
showsPrec :: Int -> ClassFile -> ShowS
$cshow :: ClassFile -> String
show :: ClassFile -> String
$cshowList :: [ClassFile] -> ShowS
showList :: [ClassFile] -> ShowS
Show)

data FieldInfo = FieldInfo
    { FieldInfo -> Word16
accessFlags :: Word16
    , FieldInfo -> Word16
nameIndex :: Word16
    , FieldInfo -> Word16
descriptorIndex :: Word16
    , FieldInfo -> Vector AttributeInfo
attributes :: Vector AttributeInfo
    }
    deriving (Int -> FieldInfo -> ShowS
[FieldInfo] -> ShowS
FieldInfo -> String
(Int -> FieldInfo -> ShowS)
-> (FieldInfo -> String)
-> ([FieldInfo] -> ShowS)
-> Show FieldInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FieldInfo -> ShowS
showsPrec :: Int -> FieldInfo -> ShowS
$cshow :: FieldInfo -> String
show :: FieldInfo -> String
$cshowList :: [FieldInfo] -> ShowS
showList :: [FieldInfo] -> ShowS
Show)

data AttributeInfo = AttributeInfo
    { AttributeInfo -> Word16
nameIndex :: Word16
    , AttributeInfo -> Attribute
info :: Attribute
    }
    deriving (Int -> AttributeInfo -> ShowS
[AttributeInfo] -> ShowS
AttributeInfo -> String
(Int -> AttributeInfo -> ShowS)
-> (AttributeInfo -> String)
-> ([AttributeInfo] -> ShowS)
-> Show AttributeInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AttributeInfo -> ShowS
showsPrec :: Int -> AttributeInfo -> ShowS
$cshow :: AttributeInfo -> String
show :: AttributeInfo -> String
$cshowList :: [AttributeInfo] -> ShowS
showList :: [AttributeInfo] -> ShowS
Show)

data Attribute
    = CodeAttribute
        { Attribute -> Word16
maxStack :: Word16
        , Attribute -> Word16
maxLocals :: Word16
        , Attribute -> Vector Instruction
code :: Vector Instruction
        , Attribute -> Vector ExceptionTableEntry
exceptionTable :: Vector ExceptionTableEntry
        , Attribute -> Vector AttributeInfo
codeAttributes :: Vector AttributeInfo
        }
    | InnerClassesAttribute (Vector InnerClassInfo)
    | LineNumberTableAttribute (Vector LineNumberTableEntry)
    | StackMapTableAttribute (Vector StackMapFrame)
    | ConstantValueAttribute Word16
    | SourceFileAttribute Word16
    | BootstrapMethodsAttribute (Vector BootstrapMethod)
    deriving (Int -> Attribute -> ShowS
[Attribute] -> ShowS
Attribute -> String
(Int -> Attribute -> ShowS)
-> (Attribute -> String)
-> ([Attribute] -> ShowS)
-> Show Attribute
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Attribute -> ShowS
showsPrec :: Int -> Attribute -> ShowS
$cshow :: Attribute -> String
show :: Attribute -> String
$cshowList :: [Attribute] -> ShowS
showList :: [Attribute] -> ShowS
Show)

data InnerClassInfo = InnerClassInfo
    { InnerClassInfo -> Word16
innerClassInfo :: Word16
    , InnerClassInfo -> Word16
outerClassInfo :: Word16
    , InnerClassInfo -> Word16
innerName :: Word16
    , InnerClassInfo -> Word16
accessFlags :: Word16
    }
    deriving (Int -> InnerClassInfo -> ShowS
[InnerClassInfo] -> ShowS
InnerClassInfo -> String
(Int -> InnerClassInfo -> ShowS)
-> (InnerClassInfo -> String)
-> ([InnerClassInfo] -> ShowS)
-> Show InnerClassInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> InnerClassInfo -> ShowS
showsPrec :: Int -> InnerClassInfo -> ShowS
$cshow :: InnerClassInfo -> String
show :: InnerClassInfo -> String
$cshowList :: [InnerClassInfo] -> ShowS
showList :: [InnerClassInfo] -> ShowS
Show)

data LineNumberTableEntry = LineNumberTableEntry
    { LineNumberTableEntry -> Word16
startPc :: U2
    , LineNumberTableEntry -> Word16
lineNumber :: U2
    }
    deriving (Int -> LineNumberTableEntry -> ShowS
[LineNumberTableEntry] -> ShowS
LineNumberTableEntry -> String
(Int -> LineNumberTableEntry -> ShowS)
-> (LineNumberTableEntry -> String)
-> ([LineNumberTableEntry] -> ShowS)
-> Show LineNumberTableEntry
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> LineNumberTableEntry -> ShowS
showsPrec :: Int -> LineNumberTableEntry -> ShowS
$cshow :: LineNumberTableEntry -> String
show :: LineNumberTableEntry -> String
$cshowList :: [LineNumberTableEntry] -> ShowS
showList :: [LineNumberTableEntry] -> ShowS
Show)

{- | The stack map frame types are defined as follows:
> union stack_map_frame {
>    same_frame;
>    same_locals_1_stack_item_frame;
>    same_locals_1_stack_item_frame_extended;
>    chop_frame;
>    same_frame_extended;
>    append_frame;
>    full_frame;
>}
-}
data StackMapFrame
    = -- | 0-63
      SameFrame U1
    | -- |
      -- >       same_locals_1_stack_item_frame {
      -- >          u1 frame_type = SAME_LOCALS_1_STACK_ITEM; /* 64-127 */
      -- >          verification_type_info stack[1];
      -- >      }
      SameLocals1StackItemFrame VerificationTypeInfo U1
    | SameLocals1StackItemFrameExtended VerificationTypeInfo U2
    | SameFrameExtended U2
    | ChopFrame U1 U2
    | AppendFrame (Vector VerificationTypeInfo) U2
    | FullFrame (Vector VerificationTypeInfo) (Vector VerificationTypeInfo) U2
    deriving (Int -> StackMapFrame -> ShowS
[StackMapFrame] -> ShowS
StackMapFrame -> String
(Int -> StackMapFrame -> ShowS)
-> (StackMapFrame -> String)
-> ([StackMapFrame] -> ShowS)
-> Show StackMapFrame
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> StackMapFrame -> ShowS
showsPrec :: Int -> StackMapFrame -> ShowS
$cshow :: StackMapFrame -> String
show :: StackMapFrame -> String
$cshowList :: [StackMapFrame] -> ShowS
showList :: [StackMapFrame] -> ShowS
Show)

data VerificationTypeInfo
    = TopVariableInfo
    | IntegerVariableInfo
    | FloatVariableInfo
    | LongVariableInfo
    | DoubleVariableInfo
    | NullVariableInfo
    | UninitializedThisVariableInfo
    | ObjectVariableInfo Word16
    | UninitializedVariableInfo U2
    deriving (Int -> VerificationTypeInfo -> ShowS
[VerificationTypeInfo] -> ShowS
VerificationTypeInfo -> String
(Int -> VerificationTypeInfo -> ShowS)
-> (VerificationTypeInfo -> String)
-> ([VerificationTypeInfo] -> ShowS)
-> Show VerificationTypeInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> VerificationTypeInfo -> ShowS
showsPrec :: Int -> VerificationTypeInfo -> ShowS
$cshow :: VerificationTypeInfo -> String
show :: VerificationTypeInfo -> String
$cshowList :: [VerificationTypeInfo] -> ShowS
showList :: [VerificationTypeInfo] -> ShowS
Show)

data BootstrapMethod = BootstrapMethod
    { BootstrapMethod -> Word16
bootstrapMethodRef :: Word16
    , BootstrapMethod -> Vector Word16
bootstrapArguments :: Vector Word16
    }
    deriving (Int -> BootstrapMethod -> ShowS
[BootstrapMethod] -> ShowS
BootstrapMethod -> String
(Int -> BootstrapMethod -> ShowS)
-> (BootstrapMethod -> String)
-> ([BootstrapMethod] -> ShowS)
-> Show BootstrapMethod
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BootstrapMethod -> ShowS
showsPrec :: Int -> BootstrapMethod -> ShowS
$cshow :: BootstrapMethod -> String
show :: BootstrapMethod -> String
$cshowList :: [BootstrapMethod] -> ShowS
showList :: [BootstrapMethod] -> ShowS
Show, BootstrapMethod -> BootstrapMethod -> Bool
(BootstrapMethod -> BootstrapMethod -> Bool)
-> (BootstrapMethod -> BootstrapMethod -> Bool)
-> Eq BootstrapMethod
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BootstrapMethod -> BootstrapMethod -> Bool
== :: BootstrapMethod -> BootstrapMethod -> Bool
$c/= :: BootstrapMethod -> BootstrapMethod -> Bool
/= :: BootstrapMethod -> BootstrapMethod -> Bool
Eq, Eq BootstrapMethod
Eq BootstrapMethod =>
(BootstrapMethod -> BootstrapMethod -> Ordering)
-> (BootstrapMethod -> BootstrapMethod -> Bool)
-> (BootstrapMethod -> BootstrapMethod -> Bool)
-> (BootstrapMethod -> BootstrapMethod -> Bool)
-> (BootstrapMethod -> BootstrapMethod -> Bool)
-> (BootstrapMethod -> BootstrapMethod -> BootstrapMethod)
-> (BootstrapMethod -> BootstrapMethod -> BootstrapMethod)
-> Ord BootstrapMethod
BootstrapMethod -> BootstrapMethod -> Bool
BootstrapMethod -> BootstrapMethod -> Ordering
BootstrapMethod -> BootstrapMethod -> BootstrapMethod
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 :: BootstrapMethod -> BootstrapMethod -> Ordering
compare :: BootstrapMethod -> BootstrapMethod -> Ordering
$c< :: BootstrapMethod -> BootstrapMethod -> Bool
< :: BootstrapMethod -> BootstrapMethod -> Bool
$c<= :: BootstrapMethod -> BootstrapMethod -> Bool
<= :: BootstrapMethod -> BootstrapMethod -> Bool
$c> :: BootstrapMethod -> BootstrapMethod -> Bool
> :: BootstrapMethod -> BootstrapMethod -> Bool
$c>= :: BootstrapMethod -> BootstrapMethod -> Bool
>= :: BootstrapMethod -> BootstrapMethod -> Bool
$cmax :: BootstrapMethod -> BootstrapMethod -> BootstrapMethod
max :: BootstrapMethod -> BootstrapMethod -> BootstrapMethod
$cmin :: BootstrapMethod -> BootstrapMethod -> BootstrapMethod
min :: BootstrapMethod -> BootstrapMethod -> BootstrapMethod
Ord)

data ExceptionTableEntry = ExceptionTableEntry
    { ExceptionTableEntry -> Word16
startPc :: Word16
    , ExceptionTableEntry -> Word16
endPc :: Word16
    , ExceptionTableEntry -> Word16
handlerPc :: Word16
    , ExceptionTableEntry -> Word16
catchType :: Word16
    }
    deriving (Int -> ExceptionTableEntry -> ShowS
[ExceptionTableEntry] -> ShowS
ExceptionTableEntry -> String
(Int -> ExceptionTableEntry -> ShowS)
-> (ExceptionTableEntry -> String)
-> ([ExceptionTableEntry] -> ShowS)
-> Show ExceptionTableEntry
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ExceptionTableEntry -> ShowS
showsPrec :: Int -> ExceptionTableEntry -> ShowS
$cshow :: ExceptionTableEntry -> String
show :: ExceptionTableEntry -> String
$cshowList :: [ExceptionTableEntry] -> ShowS
showList :: [ExceptionTableEntry] -> ShowS
Show)

data MethodInfo = MethodInfo
    { MethodInfo -> Word16
accessFlags :: Word16
    , MethodInfo -> Word16
nameIndex :: Word16
    , MethodInfo -> Word16
descriptorIndex :: Word16
    , MethodInfo -> Vector AttributeInfo
attributes :: Vector AttributeInfo
    }
    deriving (Int -> MethodInfo -> ShowS
[MethodInfo] -> ShowS
MethodInfo -> String
(Int -> MethodInfo -> ShowS)
-> (MethodInfo -> String)
-> ([MethodInfo] -> ShowS)
-> Show MethodInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MethodInfo -> ShowS
showsPrec :: Int -> MethodInfo -> ShowS
$cshow :: MethodInfo -> String
show :: MethodInfo -> String
$cshowList :: [MethodInfo] -> ShowS
showList :: [MethodInfo] -> ShowS
Show)

putConstantPool :: V.Vector ConstantPoolInfo -> Put
putConstantPool :: Vector ConstantPoolInfo -> Put
putConstantPool Vector ConstantPoolInfo
entries = do
    Word16 -> Put
putWord16be (Word16 -> Put) -> Word16 -> Put
forall a b. (a -> b) -> a -> b
$ Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Vector ConstantPoolInfo -> Int
forall a. Vector a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Vector ConstantPoolInfo
entries Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
    (ConstantPoolInfo -> Put) -> Vector ConstantPoolInfo -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ConstantPoolInfo -> Put
forall a. WriteBinary a => a -> Put
writeBinary Vector ConstantPoolInfo
entries

putInterfaceTable :: Vector Word16 -> Put
putInterfaceTable :: Vector Word16 -> Put
putInterfaceTable = (Word16 -> Put) -> Vector Word16 -> Put
forall a i (t :: * -> *).
(WriteBinary a, Integral i, Foldable t) =>
(i -> Put) -> t a -> Put
writeList Word16 -> Put
putWord16be

putFieldTable :: Vector FieldInfo -> Put
putFieldTable :: Vector FieldInfo -> Put
putFieldTable = (Word16 -> Put) -> Vector FieldInfo -> Put
forall a i (t :: * -> *).
(WriteBinary a, Integral i, Foldable t) =>
(i -> Put) -> t a -> Put
writeList Word16 -> Put
putWord16be

instance WriteBinary FieldInfo where
    writeBinary :: FieldInfo -> Put
writeBinary FieldInfo{Word16
Vector AttributeInfo
accessFlags :: FieldInfo -> Word16
nameIndex :: FieldInfo -> Word16
descriptorIndex :: FieldInfo -> Word16
attributes :: FieldInfo -> Vector AttributeInfo
accessFlags :: Word16
nameIndex :: Word16
descriptorIndex :: Word16
attributes :: Vector AttributeInfo
..} = do
        Word16 -> Put
putWord16be Word16
accessFlags
        Word16 -> Put
putWord16be Word16
nameIndex
        Word16 -> Put
putWord16be Word16
descriptorIndex
        Vector AttributeInfo -> Put
putAttributes Vector AttributeInfo
attributes

putAttributes :: Vector AttributeInfo -> Put
putAttributes :: Vector AttributeInfo -> Put
putAttributes = (Word16 -> Put) -> Vector AttributeInfo -> Put
forall a i (t :: * -> *).
(WriteBinary a, Integral i, Foldable t) =>
(i -> Put) -> t a -> Put
writeList Word16 -> Put
putWord16be

instance WriteBinary AttributeInfo where
    writeBinary :: AttributeInfo -> Put
writeBinary AttributeInfo{Word16
Attribute
nameIndex :: AttributeInfo -> Word16
info :: AttributeInfo -> Attribute
nameIndex :: Word16
info :: Attribute
..} = do
        Word16 -> Put
putWord16be Word16
nameIndex
        let infoBS :: StrictByteString
infoBS = LazyByteString -> StrictByteString
B.toStrict (LazyByteString -> StrictByteString)
-> LazyByteString -> StrictByteString
forall a b. (a -> b) -> a -> b
$ Put -> LazyByteString
runPut (Put -> LazyByteString) -> Put -> LazyByteString
forall a b. (a -> b) -> a -> b
$ Attribute -> Put
putAttribute Attribute
info
        let aiLength :: Int
aiLength = StrictByteString -> Int
B.length StrictByteString
infoBS
        Word32 -> Put
putWord32be (Word32 -> Put) -> Word32 -> Put
forall a b. (a -> b) -> a -> b
$ Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
aiLength
        StrictByteString -> Put
putByteString StrictByteString
infoBS

-- | Puts the attribute data. This must not include length or name, just the actual value
putAttribute :: Attribute -> Put
putAttribute :: Attribute -> Put
putAttribute (ConstantValueAttribute Word16
cvIndex) = Word16 -> Put
putWord16be Word16
cvIndex
putAttribute (CodeAttribute Word16
maxStack Word16
maxLocals Vector Instruction
code Vector ExceptionTableEntry
exceptionTable Vector AttributeInfo
codeAttributes) = do
    Word16 -> Put
putWord16be Word16
maxStack
    Word16 -> Put
putWord16be Word16
maxLocals
    let codeStr :: StrictByteString
codeStr = LazyByteString -> StrictByteString
B.toStrict (LazyByteString -> StrictByteString)
-> LazyByteString -> StrictByteString
forall a b. (a -> b) -> a -> b
$ Builder -> LazyByteString
toLazyByteString (Builder -> LazyByteString) -> Builder -> LazyByteString
forall a b. (a -> b) -> a -> b
$ Put -> Builder
forall a. PutM a -> Builder
execPut (Put -> Builder) -> Put -> Builder
forall a b. (a -> b) -> a -> b
$ (Instruction -> Put) -> Vector Instruction -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Instruction -> Put
forall a. WriteBinary a => a -> Put
writeBinary Vector Instruction
code
    Word32 -> Put
putWord32be (Word32 -> Put) -> Word32 -> Put
forall a b. (a -> b) -> a -> b
$ Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word32) -> Int -> Word32
forall a b. (a -> b) -> a -> b
$ StrictByteString -> Int
B.length StrictByteString
codeStr
    StrictByteString -> Put
putByteString StrictByteString
codeStr
    Vector ExceptionTableEntry -> Put
putExceptionTable Vector ExceptionTableEntry
exceptionTable
    Vector AttributeInfo -> Put
putAttributes Vector AttributeInfo
codeAttributes
putAttribute (InnerClassesAttribute Vector InnerClassInfo
classes) = do
    Word16 -> Put
putWord16be (Word16 -> Put) -> Word16 -> Put
forall a b. (a -> b) -> a -> b
$ Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word16) -> Int -> Word16
forall a b. (a -> b) -> a -> b
$ Vector InnerClassInfo -> Int
forall a. Vector a -> Int
V.length Vector InnerClassInfo
classes
    (InnerClassInfo -> Put) -> Vector InnerClassInfo -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ InnerClassInfo -> Put
putInnerClassInfo Vector InnerClassInfo
classes
  where
    putInnerClassInfo :: InnerClassInfo -> Put
    putInnerClassInfo :: InnerClassInfo -> Put
putInnerClassInfo InnerClassInfo{Word16
innerClassInfo :: InnerClassInfo -> Word16
outerClassInfo :: InnerClassInfo -> Word16
innerName :: InnerClassInfo -> Word16
accessFlags :: InnerClassInfo -> Word16
innerClassInfo :: Word16
outerClassInfo :: Word16
innerName :: Word16
accessFlags :: Word16
..} = do
        Word16 -> Put
putWord16be Word16
innerClassInfo
        Word16 -> Put
putWord16be Word16
outerClassInfo
        Word16 -> Put
putWord16be Word16
innerName
        Word16 -> Put
putWord16be Word16
accessFlags
putAttribute (SourceFileAttribute Word16
sfIndex) = do
    Word16 -> Put
putWord16be Word16
sfIndex
putAttribute (BootstrapMethodsAttribute Vector BootstrapMethod
bms) = do
    Word16 -> Put
putWord16be (Word16 -> Put) -> Word16 -> Put
forall a b. (a -> b) -> a -> b
$ Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word16) -> Int -> Word16
forall a b. (a -> b) -> a -> b
$ Vector BootstrapMethod -> Int
forall a. Vector a -> Int
V.length Vector BootstrapMethod
bms
    (BootstrapMethod -> Put) -> Vector BootstrapMethod -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ BootstrapMethod -> Put
putBootstrapMethod Vector BootstrapMethod
bms
putAttribute (LineNumberTableAttribute Vector LineNumberTableEntry
lns) = do
    Word16 -> Put
putWord16be (Word16 -> Put) -> Word16 -> Put
forall a b. (a -> b) -> a -> b
$ Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word16) -> Int -> Word16
forall a b. (a -> b) -> a -> b
$ Vector LineNumberTableEntry -> Int
forall a. Vector a -> Int
V.length Vector LineNumberTableEntry
lns
    (LineNumberTableEntry -> Put) -> Vector LineNumberTableEntry -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ LineNumberTableEntry -> Put
putLineNumberEntry Vector LineNumberTableEntry
lns
  where
    putLineNumberEntry :: LineNumberTableEntry -> Put
    putLineNumberEntry :: LineNumberTableEntry -> Put
putLineNumberEntry LineNumberTableEntry{Word16
startPc :: LineNumberTableEntry -> Word16
lineNumber :: LineNumberTableEntry -> Word16
startPc :: Word16
lineNumber :: Word16
..} = do
        Word16 -> Put
putWord16be Word16
startPc
        Word16 -> Put
putWord16be Word16
lineNumber
putAttribute (StackMapTableAttribute Vector StackMapFrame
frames) = do
    Word16 -> Put
putWord16be (Word16 -> Put) -> Word16 -> Put
forall a b. (a -> b) -> a -> b
$ Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word16) -> Int -> Word16
forall a b. (a -> b) -> a -> b
$ Vector StackMapFrame -> Int
forall a. Vector a -> Int
V.length Vector StackMapFrame
frames
    (StackMapFrame -> Put) -> Vector StackMapFrame -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ StackMapFrame -> Put
putStackMapFrame Vector StackMapFrame
frames
  where
    putStackMapFrame :: StackMapFrame -> Put
    putStackMapFrame :: StackMapFrame -> Put
putStackMapFrame (SameFrame Word8
offset) = Word8 -> Put
putWord8 Word8
offset
    putStackMapFrame (SameFrameExtended Word16
offset) = do
        Word8 -> Put
putWord8 Word8
251
        Word16 -> Put
putWord16be Word16
offset
    putStackMapFrame (SameLocals1StackItemFrame VerificationTypeInfo
info Word8
offset) = do
        Word8 -> Put
putWord8 (Word8
64 Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
offset) -- frame_type = 64 + offset
        VerificationTypeInfo -> Put
putVerificationTypeInfo VerificationTypeInfo
info
    putStackMapFrame (SameLocals1StackItemFrameExtended VerificationTypeInfo
info Word16
offset) = do
        Word8 -> Put
putWord8 Word8
247
        Word16 -> Put
putWord16be Word16
offset
        VerificationTypeInfo -> Put
putVerificationTypeInfo VerificationTypeInfo
info
    putStackMapFrame (ChopFrame Word8
chop Word16
label) = do
        Word8 -> Put
putWord8 (Word8
251 Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
chop) -- chop = 251 - frame_type => frame_type = 251 - chop
        Word16 -> Put
putWord16be Word16
label
    putStackMapFrame (AppendFrame Vector VerificationTypeInfo
infos Word16
offset) = do
        Word8 -> Put
putWord8 (Word8
251 Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Vector VerificationTypeInfo -> Int
forall a. Vector a -> Int
V.length Vector VerificationTypeInfo
infos)) -- frame_type = 251 + number_of_locals
        Word16 -> Put
putWord16be Word16
offset
        (VerificationTypeInfo -> Put) -> Vector VerificationTypeInfo -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ VerificationTypeInfo -> Put
putVerificationTypeInfo Vector VerificationTypeInfo
infos
    putStackMapFrame (FullFrame Vector VerificationTypeInfo
locals Vector VerificationTypeInfo
stack Word16
offset) = do
        Word8 -> Put
putWord8 Word8
255
        Word16 -> Put
putWord16be Word16
offset
        Word16 -> Put
putWord16be (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word16) -> Int -> Word16
forall a b. (a -> b) -> a -> b
$ Vector VerificationTypeInfo -> Int
forall a. Vector a -> Int
V.length Vector VerificationTypeInfo
locals)
        (VerificationTypeInfo -> Put) -> Vector VerificationTypeInfo -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ VerificationTypeInfo -> Put
putVerificationTypeInfo Vector VerificationTypeInfo
locals
        Word16 -> Put
putWord16be (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word16) -> Int -> Word16
forall a b. (a -> b) -> a -> b
$ Vector VerificationTypeInfo -> Int
forall a. Vector a -> Int
V.length Vector VerificationTypeInfo
stack)
        (VerificationTypeInfo -> Put) -> Vector VerificationTypeInfo -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ VerificationTypeInfo -> Put
putVerificationTypeInfo Vector VerificationTypeInfo
stack

    putVerificationTypeInfo :: VerificationTypeInfo -> Put
    putVerificationTypeInfo :: VerificationTypeInfo -> Put
putVerificationTypeInfo VerificationTypeInfo
TopVariableInfo = Word8 -> Put
putWord8 Word8
MagicNumbers.verificationType_info_TopVariableInfo
    putVerificationTypeInfo VerificationTypeInfo
IntegerVariableInfo = Word8 -> Put
putWord8 Word8
MagicNumbers.verificationType_info_IntegerVariableInfo
    putVerificationTypeInfo VerificationTypeInfo
FloatVariableInfo = Word8 -> Put
putWord8 Word8
MagicNumbers.verificationType_info_FloatVariableInfo
    putVerificationTypeInfo VerificationTypeInfo
LongVariableInfo = Word8 -> Put
putWord8 Word8
MagicNumbers.verificationType_info_LongVariableInfo
    putVerificationTypeInfo VerificationTypeInfo
DoubleVariableInfo = Word8 -> Put
putWord8 Word8
MagicNumbers.verificationType_info_DoubleVariableInfo
    putVerificationTypeInfo VerificationTypeInfo
NullVariableInfo = Word8 -> Put
putWord8 Word8
MagicNumbers.verificationType_info_NullVariableInfo
    putVerificationTypeInfo VerificationTypeInfo
UninitializedThisVariableInfo = Word8 -> Put
putWord8 Word8
MagicNumbers.verificationType_info_UninitializedThisVariableInfo
    putVerificationTypeInfo (ObjectVariableInfo Word16
index) = do
        Word8 -> Put
putWord8 Word8
MagicNumbers.verificationType_info_ObjectVariableInfo
        Word16 -> Put
putWord16be Word16
index
    putVerificationTypeInfo (UninitializedVariableInfo Word16
offset) = do
        Word8 -> Put
putWord8 Word8
MagicNumbers.verificationType_info_UninitializedVariableInfo
        Word16 -> Put
putWord16be Word16
offset

putBootstrapMethod :: BootstrapMethod -> Put
putBootstrapMethod :: BootstrapMethod -> Put
putBootstrapMethod BootstrapMethod{Word16
Vector Word16
bootstrapMethodRef :: BootstrapMethod -> Word16
bootstrapArguments :: BootstrapMethod -> Vector Word16
bootstrapMethodRef :: Word16
bootstrapArguments :: Vector Word16
..} = do
    Word16 -> Put
putWord16be Word16
bootstrapMethodRef
    Word16 -> Put
putWord16be (Word16 -> Put) -> Word16 -> Put
forall a b. (a -> b) -> a -> b
$ Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word16) -> Int -> Word16
forall a b. (a -> b) -> a -> b
$ Vector Word16 -> Int
forall a. Vector a -> Int
V.length Vector Word16
bootstrapArguments
    (Word16 -> Put) -> Vector Word16 -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Word16 -> Put
putWord16be Vector Word16
bootstrapArguments

putExceptionTable :: Vector ExceptionTableEntry -> Put
putExceptionTable :: Vector ExceptionTableEntry -> Put
putExceptionTable = (Word16 -> Put) -> Vector ExceptionTableEntry -> Put
forall a i (t :: * -> *).
(WriteBinary a, Integral i, Foldable t) =>
(i -> Put) -> t a -> Put
writeList Word16 -> Put
putWord16be

instance WriteBinary ExceptionTableEntry where
    writeBinary :: ExceptionTableEntry -> Put
writeBinary (ExceptionTableEntry{Word16
startPc :: ExceptionTableEntry -> Word16
endPc :: ExceptionTableEntry -> Word16
handlerPc :: ExceptionTableEntry -> Word16
catchType :: ExceptionTableEntry -> Word16
startPc :: Word16
endPc :: Word16
handlerPc :: Word16
catchType :: Word16
..}) = do
        Word16 -> Put
putWord16be Word16
startPc
        Word16 -> Put
putWord16be Word16
endPc
        Word16 -> Put
putWord16be Word16
handlerPc
        Word16 -> Put
putWord16be Word16
catchType

putMethodTable :: Vector MethodInfo -> Put
putMethodTable :: Vector MethodInfo -> Put
putMethodTable = (Word16 -> Put) -> Vector MethodInfo -> Put
forall a i (t :: * -> *).
(WriteBinary a, Integral i, Foldable t) =>
(i -> Put) -> t a -> Put
writeList Word16 -> Put
putWord16be

instance WriteBinary MethodInfo where
    writeBinary :: MethodInfo -> Put
writeBinary MethodInfo{Word16
Vector AttributeInfo
accessFlags :: MethodInfo -> Word16
nameIndex :: MethodInfo -> Word16
descriptorIndex :: MethodInfo -> Word16
attributes :: MethodInfo -> Vector AttributeInfo
accessFlags :: Word16
nameIndex :: Word16
descriptorIndex :: Word16
attributes :: Vector AttributeInfo
..} = do
        Word16 -> Put
putWord16be Word16
accessFlags
        Word16 -> Put
putWord16be Word16
nameIndex
        Word16 -> Put
putWord16be Word16
descriptorIndex
        Vector AttributeInfo -> Put
putAttributes Vector AttributeInfo
attributes

instance WriteBinary ClassFile where
    writeBinary :: ClassFile -> Put
writeBinary ClassFile{Word16
Word32
Vector Word16
Vector ConstantPoolInfo
Vector MethodInfo
Vector AttributeInfo
Vector FieldInfo
MinorVersion
MajorVersion
magic :: ClassFile -> Word32
minorVersion :: ClassFile -> MinorVersion
majorVersion :: ClassFile -> MajorVersion
constantPool :: ClassFile -> Vector ConstantPoolInfo
accessFlags :: ClassFile -> Word16
thisClass :: ClassFile -> Word16
superClass :: ClassFile -> Word16
interfaces :: ClassFile -> Vector Word16
fields :: ClassFile -> Vector FieldInfo
methods :: ClassFile -> Vector MethodInfo
attributes :: ClassFile -> Vector AttributeInfo
magic :: Word32
minorVersion :: MinorVersion
majorVersion :: MajorVersion
constantPool :: Vector ConstantPoolInfo
accessFlags :: Word16
thisClass :: Word16
superClass :: Word16
interfaces :: Vector Word16
fields :: Vector FieldInfo
methods :: Vector MethodInfo
attributes :: Vector AttributeInfo
..} = do
        Word32 -> Put
putWord32be Word32
magic
        Word16 -> Put
putWord16be (MinorVersion -> Word16
unwrapMinor MinorVersion
minorVersion)
        Word16 -> Put
putWord16be (MajorVersion -> Word16
unwrapMajor MajorVersion
majorVersion)
        Vector ConstantPoolInfo -> Put
putConstantPool Vector ConstantPoolInfo
constantPool
        Word16 -> Put
putWord16be Word16
accessFlags
        Word16 -> Put
putWord16be Word16
thisClass
        Word16 -> Put
putWord16be Word16
superClass
        Vector Word16 -> Put
putInterfaceTable Vector Word16
interfaces

        Vector FieldInfo -> Put
putFieldTable Vector FieldInfo
fields
        Vector MethodInfo -> Put
putMethodTable Vector MethodInfo
methods
        Vector AttributeInfo -> Put
putAttributes Vector AttributeInfo
attributes