{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} module Foreign.JNI.Internal where import Data.Text (Text) import qualified Data.Text as Text import qualified Foreign.JNI.String as JNI -- | A reference type name is not just any 'JNI.String', but a fully qualified -- identifier well-formed by construction. newtype ReferenceTypeName = ReferenceTypeName JNI.String deriving (Eq, Ord) instance Show ReferenceTypeName where show (ReferenceTypeName str) = show str -- | A string representing a signature, well-formed by construction. newtype Signature = Signature JNI.String deriving (Eq, Ord) instance Show Signature where show (Signature str) = show str -- | A string representing a method signature, well-formed by construction. newtype MethodSignature = MethodSignature JNI.String deriving (Eq, Ord) instance Show MethodSignature where show (MethodSignature str) = show str jniMethodToJavaSignature :: Text -> Either String ([Text], Text) jniMethodToJavaSignature sig = do (argTypes, rest1) <- dropChar '(' sig >>= many toJavaType (returnType, rest2) <- dropChar ')' rest1 >>= toJavaType if Text.null rest2 then return (argTypes, returnType) else Left $ "Unexpected suffix " ++ show rest2 where dropChar c t = case Text.uncons t of Just (c', t') | c == c' -> Right t' _ -> Left $ unwords [ "Expected ", show c, "but found", show t] many p = go id where go acc t = case p t of Left _ -> Right (acc [], t) Right (x, t') -> go (acc . (x:)) t' toJavaType t = case Text.uncons t of Just (c, t') -> case c of 'L' -> case Text.breakOn ";" t' of (jtype, rest) -> Right (Text.map substSlash jtype, Text.drop 1 rest) '[' -> fmap (\(jtype, rest) -> (jtype <> "[]", rest)) (toJavaType t') 'Z' -> Right ("boolean", t') 'B' -> Right ("byte", t') 'C' -> Right ("char", t') 'S' -> Right ("short", t') 'I' -> Right ("int", t') 'J' -> Right ("long", t') 'F' -> Right ("float", t') 'D' -> Right ("double", t') 'V' -> Right ("void", t') _ -> Left $ "Unexpected char " ++ show c ++ " at " ++ show t' Nothing -> Left "Unexpected empty text" substSlash = \case '/' -> '.' c -> c