diff --git a/java-classfile.cabal b/java-classfile.cabal index 09294fe..0ee1afa 100644 --- a/java-classfile.cabal +++ b/java-classfile.cabal @@ -29,6 +29,7 @@ library Language.Java.Classfile.Extract Language.Java.Classfile.Extractable Language.Java.Classfile.FromBigEndian + Language.Java.Classfile.Magic Language.Java.Classfile.Version other-modules: Paths_java_classfile diff --git a/src/Language/Java/Classfile/Extract.hs b/src/Language/Java/Classfile/Extract.hs index d560afe..352e951 100644 --- a/src/Language/Java/Classfile/Extract.hs +++ b/src/Language/Java/Classfile/Extract.hs @@ -1,6 +1,6 @@ {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE InstanceSigs #-} -module Language.Java.Classfile.Extract (Extract(), bytes, runExtract) where +module Language.Java.Classfile.Extract (Extract(), bytes, runExtract, expectRaw, expectEqual) where import Data.ByteString.Lazy (ByteString) import qualified Data.ByteString.Lazy as ByteString @@ -47,6 +47,20 @@ bytes count = Extract $ \ input -> let then Fail else Done rest bs +expectRaw :: ByteString -> Extract ByteString +expectRaw e = Extract $ \ input -> let + (actual, rest) = ByteString.splitAt (ByteString.length e) input + in case actual == e of + True -> Done rest actual + False -> Fail + +expectEqual :: Eq a => Extract a -> a -> Extract a +expectEqual (Extract computeActual) expected = Extract $ \ input -> case computeActual input of + Done rest actual -> if actual == expected + then Done rest actual + else Fail + Fail -> Fail + {- It seems I cannot define a lawful monad instance instance Monad Extract where (>>=) :: Extract a -> (a -> Extract b) -> Extract b diff --git a/src/Language/Java/Classfile/Extractable.hs b/src/Language/Java/Classfile/Extractable.hs index 011c87e..0e8e126 100644 --- a/src/Language/Java/Classfile/Extractable.hs +++ b/src/Language/Java/Classfile/Extractable.hs @@ -2,16 +2,15 @@ {-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE UndecidableInstances #-} -module Language.Java.Classfile.Extractable (Extractable(extract)) where +module Language.Java.Classfile.Extractable (Extractable(extract), expectConstant) where -import Language.Java.Classfile.Extract (Extract, bytes) +import Language.Java.Classfile.Extract (Extract, bytes, expectEqual) import Data.Word (Word8, Word16, Word32) import qualified Data.ByteString.Lazy as ByteString import Data.ByteString.Lazy (ByteString) import Data.Bits (Bits(shiftL, (.|.))) import GHC.Generics (U1 (U1), (:*:) ((:*:)), (:+:) (L1, R1), M1 (M1), K1 (K1), Generic (Rep, to), Generically (Generically)) -import Control.Applicative ((<|>)) - +import Control.Applicative ((<|>), empty) class Extractable a where extract :: Extract a @@ -28,6 +27,9 @@ instance Extractable Word32 where extract :: Extract Word32 extract = build <$> bytes 4 +expectConstant :: (Extractable a, Eq a) => a -> Extract a +expectConstant = expectEqual extract + build :: (Bits a, Num a) => ByteString -> a build = ByteString.foldl' shiftOr 0 diff --git a/src/Language/Java/Classfile/Version.hs b/src/Language/Java/Classfile/Version.hs index 65354a2..f2e2198 100644 --- a/src/Language/Java/Classfile/Version.hs +++ b/src/Language/Java/Classfile/Version.hs @@ -15,8 +15,8 @@ data Version = Version deriving Extractable via Generically Version -- >>> import Language.Java.Classfile.Extractable (Extractable(extract)) --- >>> import Language.Java.Classfile.Extract (runExtract) --- >>> :set -XOVerloadedLists --- >>> runExtract (fromList [0, 0, 0, 0]) extract :: Version --- Variable not in scope: fromList :: [a0_a3mwi[tau:1]] -> ByteString +-- >>> import Language.Java.Classfile.Extract (runExtract, Extract) +-- >>> :set -XOverloadedLists +-- >>> runExtract [1, 2, 0, 2] (extract :: Extract Version) +-- Just ("",Version {minor = 258, major = 2})