Dev: add support of Set

This commit is contained in:
Andrew Druk 2017-12-22 19:30:32 +02:00
parent b47a4f4fce
commit e72d52c36c
3 changed files with 29 additions and 6 deletions

View File

@ -23,6 +23,7 @@ let HashMapClassname = "java/util/HashMap"
let SetClassname = "java/util/Set" let SetClassname = "java/util/Set"
let UriClassname = "android/net/Uri" let UriClassname = "android/net/Uri"
let DateClassname = "java/util/Date" let DateClassname = "java/util/Date"
let HashSetClassname = "java/util/HashSet"
// MARK: Java Classes // MARK: Java Classes
var IntegerClass = try! JNI.getJavaClass("java/lang/Integer") var IntegerClass = try! JNI.getJavaClass("java/lang/Integer")
@ -36,6 +37,7 @@ let ExceptionClass = try! JNI.getJavaClass("java/lang/Exception")
let UriClass = try! JNI.getJavaClass("android/net/Uri") let UriClass = try! JNI.getJavaClass("android/net/Uri")
let DateClass = try! JNI.getJavaClass("java/util/Date") let DateClass = try! JNI.getJavaClass("java/util/Date")
let VMDebugClass = try! JNI.getJavaClass("dalvik/system/VMDebug") let VMDebugClass = try! JNI.getJavaClass("dalvik/system/VMDebug")
let HashSetClass = try! JNI.getJavaClass("java/util/HashSet")
// MARK: Java methods // MARK: Java methods
let UriConstructor = JNI.api.GetStaticMethodID(JNI.env, UriClass, "parse", "(Ljava/lang/String;)Landroid/net/Uri;") let UriConstructor = JNI.api.GetStaticMethodID(JNI.env, UriClass, "parse", "(Ljava/lang/String;)Landroid/net/Uri;")
@ -63,7 +65,10 @@ let HashMapSizeMethod = try! JNI.getJavaMethod(forClass: HashMapClassname, metho
let SetToArrayMethod = try! JNI.getJavaMethod(forClass: SetClassname, method: "toArray", sig: "()[L\(ObjectClassname);") let SetToArrayMethod = try! JNI.getJavaMethod(forClass: SetClassname, method: "toArray", sig: "()[L\(ObjectClassname);")
let ArrayListGetMethod = try! JNI.getJavaMethod(forClass: ArrayListClassname, method: "get", sig: "(I)L\(ObjectClassname);") let ArrayListGetMethod = try! JNI.getJavaMethod(forClass: ArrayListClassname, method: "get", sig: "(I)L\(ObjectClassname);")
let ArrayListSizeMethod = try! JNI.getJavaMethod(forClass: ArrayListClassname, method: "size", sig: "()I") let ArrayListSizeMethod = try! JNI.getJavaMethod(forClass: ArrayListClassname, method: "size", sig: "()I")
let ArrayListAddMethod = try! JNI.getJavaMethod(forClass: ArrayListClassname, method: "add", sig: "(Ljava/lang/Object;)Z") let CollectionAddMethod = try! JNI.getJavaMethod(forClass: "java/util/Collection", method: "add", sig: "(Ljava/lang/Object;)Z")
let CollectionIteratorMethod = try! JNI.getJavaMethod(forClass: "java/util/Collection", method: "iterator", sig: "()Ljava/util/Iterator;")
let CollectionSizeMethod = try! JNI.getJavaMethod(forClass: "java/util/Collection", method: "size", sig: "()I")
let IteratorNextMethod = try! JNI.getJavaMethod(forClass: "java/util/Iterator", method: "next", sig: "()Ljava/lang/Object;")
let DateGetTimeMethod = try! JNI.getJavaMethod(forClass: "java/util/Date", method: "getTime", sig:"()J") let DateGetTimeMethod = try! JNI.getJavaMethod(forClass: "java/util/Date", method: "getTime", sig:"()J")
let VMDebugDumpReferenceTablesMethod = JNI.api.GetStaticMethodID(JNI.env, VMDebugClass, "dumpReferenceTables", "()V") let VMDebugDumpReferenceTablesMethod = JNI.api.GetStaticMethodID(JNI.env, VMDebugClass, "dumpReferenceTables", "()V")

View File

@ -449,13 +449,17 @@ fileprivate class JavaArrayContainer: UnkeyedDecodingContainer {
let decoder: JavaDecoder let decoder: JavaDecoder
let jniStorage: JNIStorageObject let jniStorage: JNIStorageObject
let javaObject: jobject let javaIterator: jobject
fileprivate init(decoder: JavaDecoder, jniStorage: JNIStorageObject) { fileprivate init(decoder: JavaDecoder, jniStorage: JNIStorageObject) {
self.decoder = decoder self.decoder = decoder
self.jniStorage = jniStorage self.jniStorage = jniStorage
self.javaObject = jniStorage.javaObject self.count = Int(JNI.CallIntMethod(jniStorage.javaObject, methodID: CollectionSizeMethod))
self.count = Int(JNI.CallIntMethod(self.javaObject, methodID: ArrayListSizeMethod)) self.javaIterator = JNI.CallObjectMethod(jniStorage.javaObject, methodID: CollectionIteratorMethod)!
}
deinit {
JNI.DeleteLocalRef(javaIterator)
} }
func decodeNil() throws -> Bool { func decodeNil() throws -> Bool {
@ -463,7 +467,7 @@ fileprivate class JavaArrayContainer: UnkeyedDecodingContainer {
} }
func decode<T>(_ type: T.Type) throws -> T where T : Decodable { func decode<T>(_ type: T.Type) throws -> T where T : Decodable {
guard let object = JNI.CallObjectMethod(self.javaObject, methodID: ArrayListGetMethod, args: [self.index]) else { guard let object = JNI.CallObjectMethod(self.javaIterator, methodID: IteratorNextMethod) else {
throw JavaCodingError.cantFindObject("Array out of range: \(self.currentIndex)") throw JavaCodingError.cantFindObject("Array out of range: \(self.currentIndex)")
} }
defer { defer {
@ -661,6 +665,9 @@ extension JavaDecoder {
if className == ArrayListClassname { if className == ArrayListClassname {
codableType = .array codableType = .array
} }
else if className == HashSetClassname {
codableType = .array
}
else if className == HashMapClassname { else if className == HashMapClassname {
codableType = .dictionary codableType = .dictionary
} }
@ -679,6 +686,8 @@ extension JavaDecoder {
switch stringType { switch stringType {
case _ where stringType.starts(with: "Array<"): case _ where stringType.starts(with: "Array<"):
storageObject = JNIStorageObject(type: .array, javaObject: obj) storageObject = JNIStorageObject(type: .array, javaObject: obj)
case _ where stringType.starts(with: "Set<"):
storageObject = JNIStorageObject(type: .array, javaObject: obj)
case _ where stringType.starts(with: "Dictionary<"): case _ where stringType.starts(with: "Dictionary<"):
storageObject = JNIStorageObject(type: .dictionary, javaObject: obj) storageObject = JNIStorageObject(type: .dictionary, javaObject: obj)
default: default:
@ -735,6 +744,9 @@ extension JavaDecoder {
else if "\(forType)".starts(with: "Array<") { else if "\(forType)".starts(with: "Array<") {
return ArrayListClassname return ArrayListClassname
} }
else if "\(forType)".starts(with: "Set<") {
return HashSetClassname
}
else if "\(forType)".starts(with: "Dictionary<") { else if "\(forType)".starts(with: "Dictionary<") {
return HashMapClassname return HashMapClassname
} }
@ -752,6 +764,8 @@ extension JavaDecoder {
switch className { switch className {
case ArrayListClassname: case ArrayListClassname:
return .array return .array
case HashSetClassname:
return .array
case HashMapClassname: case HashMapClassname:
return .dictionary return .dictionary
default: default:

View File

@ -376,7 +376,7 @@ fileprivate class JavaArrayContainer : UnkeyedEncodingContainer {
public func encode<T : Encodable>(_ value: T) throws { public func encode<T : Encodable>(_ value: T) throws {
let storeObject = try self.encoder.box(value) let storeObject = try self.encoder.box(value)
let rewrite = JNI.CallBooleanMethod(self.javaObject, methodID: ArrayListAddMethod, args: [jvalue(l: storeObject.javaObject)]) let rewrite = JNI.CallBooleanMethod(self.javaObject, methodID: CollectionAddMethod, args: [jvalue(l: storeObject.javaObject)])
assert(rewrite == JNI.TRUE, "ArrayList should always return true from add()") assert(rewrite == JNI.TRUE, "ArrayList should always return true from add()")
count += 1 count += 1
} }
@ -645,6 +645,10 @@ extension JavaEncoder {
fullClassName = ArrayListClassname fullClassName = ArrayListClassname
storageType = .array storageType = .array
} }
else if value is Set<AnyHashable> {
fullClassName = HashSetClassname
storageType = .array
}
else { else {
fullClassName = package + "/" + String(describing: type(of: value)) fullClassName = package + "/" + String(describing: type(of: value))
storageType = .object(className: fullClassName) storageType = .object(className: fullClassName)