Dev: add support of AnyCodable and super Encoding/Decoding
This commit is contained in:
parent
fa93e4ed20
commit
31ac6c999e
|
@ -12,9 +12,10 @@ let package = Package(
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
.package(url: "https://github.com/andriydruk/java_swift.git", .branch("master")),
|
.package(url: "https://github.com/andriydruk/java_swift.git", .branch("master")),
|
||||||
|
.package(url: "https://github.com/andriydruk/swift-anycodable.git", .branch("master")),
|
||||||
],
|
],
|
||||||
targets: [
|
targets: [
|
||||||
.target(name: "JavaCoder", dependencies: ["java_swift"], path: "Sources"),
|
.target(name: "JavaCoder", dependencies: ["java_swift", "AnyCodable"], path: "Sources"),
|
||||||
],
|
],
|
||||||
swiftLanguageVersions: [4]
|
swiftLanguageVersions: [4]
|
||||||
)
|
)
|
||||||
|
|
|
@ -49,6 +49,8 @@ let BooleanConstructor = try! JNI.getJavaMethod(forClass: BooleanClassname, meth
|
||||||
|
|
||||||
let ObjectToStringMethod = try! JNI.getJavaMethod(forClass: "java/lang/Object", method: "toString", sig: "()Ljava/lang/String;")
|
let ObjectToStringMethod = try! JNI.getJavaMethod(forClass: "java/lang/Object", method: "toString", sig: "()Ljava/lang/String;")
|
||||||
let ClassGetNameMethod = try! JNI.getJavaMethod(forClass: ClassClassname, method: "getName", sig: "()L\(StringClassname);")
|
let ClassGetNameMethod = try! JNI.getJavaMethod(forClass: ClassClassname, method: "getName", sig: "()L\(StringClassname);")
|
||||||
|
let ClassGetFieldMethod = try! JNI.getJavaMethod(forClass: ClassClassname, method: "getField", sig: "(Ljava/lang/String;)Ljava/lang/reflect/Field;")
|
||||||
|
let FieldGetTypedMethod = try! JNI.getJavaMethod(forClass: "java/lang/reflect/Field", method: "getType", sig: "()L\(ClassClassname);")
|
||||||
let NumberByteValueMethod = try! JNI.getJavaMethod(forClass: "java/lang/Number", method: "byteValue", sig: "()B")
|
let NumberByteValueMethod = try! JNI.getJavaMethod(forClass: "java/lang/Number", method: "byteValue", sig: "()B")
|
||||||
let NumberShortValueMethod = try! JNI.getJavaMethod(forClass: "java/lang/Number", method: "shortValue", sig: "()S")
|
let NumberShortValueMethod = try! JNI.getJavaMethod(forClass: "java/lang/Number", method: "shortValue", sig: "()S")
|
||||||
let NumberIntValueMethod = try! JNI.getJavaMethod(forClass: "java/lang/Number", method: "intValue", sig: "()I")
|
let NumberIntValueMethod = try! JNI.getJavaMethod(forClass: "java/lang/Number", method: "intValue", sig: "()I")
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import java_swift
|
import java_swift
|
||||||
|
import AnyCodable
|
||||||
|
|
||||||
public class JavaDecoder: Decoder {
|
public class JavaDecoder: Decoder {
|
||||||
|
|
||||||
|
@ -47,7 +48,9 @@ public class JavaDecoder: Decoder {
|
||||||
let container = try JavaHashMapKeyedContainer<Key>(decoder: self, jniStorage: storageObject)
|
let container = try JavaHashMapKeyedContainer<Key>(decoder: self, jniStorage: storageObject)
|
||||||
return KeyedDecodingContainer(container)
|
return KeyedDecodingContainer(container)
|
||||||
case .object:
|
case .object:
|
||||||
return KeyedDecodingContainer.init(JavaObjectContainer(decoder: self, jniStorage: storageObject))
|
return KeyedDecodingContainer(JavaObjectContainer(decoder: self, jniStorage: storageObject))
|
||||||
|
case .anyCodable:
|
||||||
|
return KeyedDecodingContainer(JavaAnyCodableContainer(decoder: self, jniStorage: storageObject))
|
||||||
default:
|
default:
|
||||||
fatalError("Only keyed container supported here")
|
fatalError("Only keyed container supported here")
|
||||||
}
|
}
|
||||||
|
@ -119,6 +122,7 @@ fileprivate class JavaObjectContainer<K : CodingKey> : KeyedDecodingContainerPro
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
if self.decoder.missingFieldsStrategy == .ignore {
|
if self.decoder.missingFieldsStrategy == .ignore {
|
||||||
|
NSLog("Ignore error: \(error)")
|
||||||
return defaultValue
|
return defaultValue
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -195,7 +199,25 @@ fileprivate class JavaObjectContainer<K : CodingKey> : KeyedDecodingContainerPro
|
||||||
|
|
||||||
private func decodeJava<T>(_ type: T.Type, forKey key: K) throws -> T? where T : Decodable {
|
private func decodeJava<T>(_ type: T.Type, forKey key: K) throws -> T? where T : Decodable {
|
||||||
return try decodeWithMissingStrategy(defaultValue: nil) {
|
return try decodeWithMissingStrategy(defaultValue: nil) {
|
||||||
let classname = self.decoder.getJavaClassname(forType: type)
|
let classname: String
|
||||||
|
if type == AnyCodable.self {
|
||||||
|
var locals = [jobject]()
|
||||||
|
let cls = JNI.api.GetObjectClass(JNI.env, javaObject)!
|
||||||
|
let javaTypename = key.stringValue.localJavaObject(&locals)
|
||||||
|
let field = JNI.CallObjectMethod(cls, methodID: ClassGetFieldMethod, args: [jvalue(l: javaTypename)])!
|
||||||
|
let fieldClass = JNI.CallObjectMethod(field, methodID: FieldGetTypedMethod, args: [])!
|
||||||
|
let javaClassName = JNI.api.CallObjectMethodA(JNI.env, fieldClass, ClassGetNameMethod, nil)!
|
||||||
|
classname = String(javaObject: javaClassName).replacingOccurrences(of: ".", with: "/")
|
||||||
|
JNI.DeleteLocalRef(cls)
|
||||||
|
JNI.DeleteLocalRef(field)
|
||||||
|
JNI.DeleteLocalRef(fieldClass)
|
||||||
|
JNI.DeleteLocalRef(javaClassName)
|
||||||
|
_ = JNI.check(Void.self, &locals)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
classname = self.decoder.getJavaClassname(forType: type)
|
||||||
|
}
|
||||||
|
|
||||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key.stringValue, sig: "L\(classname);")
|
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key.stringValue, sig: "L\(classname);")
|
||||||
guard let object = JNI.api.GetObjectField(JNI.env, javaObject, fieldID) else {
|
guard let object = JNI.api.GetObjectField(JNI.env, javaObject, fieldID) else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -216,7 +238,8 @@ fileprivate class JavaObjectContainer<K : CodingKey> : KeyedDecodingContainerPro
|
||||||
}
|
}
|
||||||
|
|
||||||
func superDecoder() throws -> Decoder {
|
func superDecoder() throws -> Decoder {
|
||||||
throw JavaCodingError.notSupported("JavaObjectContainer.superDecoder")
|
self.decoder.storage.append(self.jniStorage)
|
||||||
|
return self.decoder
|
||||||
}
|
}
|
||||||
|
|
||||||
func superDecoder(forKey key: K) throws -> Decoder {
|
func superDecoder(forKey key: K) throws -> Decoder {
|
||||||
|
@ -502,6 +525,81 @@ fileprivate class JavaEnumContainer: SingleValueDecodingContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileprivate class JavaAnyCodableContainer<K : CodingKey> : KeyedDecodingContainerProtocol {
|
||||||
|
typealias Key = K
|
||||||
|
|
||||||
|
var codingPath = [CodingKey]()
|
||||||
|
var allKeys = [K]()
|
||||||
|
|
||||||
|
let decoder: JavaDecoder
|
||||||
|
let jniStorage: JNIStorageObject
|
||||||
|
let jniCodableType: JNIStorageType
|
||||||
|
|
||||||
|
fileprivate init(decoder: JavaDecoder, jniStorage: JNIStorageObject) {
|
||||||
|
self.decoder = decoder
|
||||||
|
self.jniStorage = jniStorage
|
||||||
|
switch jniStorage.type {
|
||||||
|
case let .anyCodable(codable):
|
||||||
|
self.jniCodableType = codable
|
||||||
|
default:
|
||||||
|
fatalError("Only .anyCodable supported here")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func contains(_ key: K) -> Bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeNil(forKey key: K) throws -> Bool {
|
||||||
|
throw JavaCodingError.notSupported("JavaObjectContainer.decodeNil(forKey: \(key)")
|
||||||
|
}
|
||||||
|
|
||||||
|
func decode<T>(_ type: T.Type, forKey key: K) throws -> T where T : Decodable {
|
||||||
|
if key.stringValue == "typeName" {
|
||||||
|
switch jniCodableType {
|
||||||
|
case let .object(className):
|
||||||
|
let subString = className.split(separator: "/").last!
|
||||||
|
return String(subString) as! T
|
||||||
|
case .array:
|
||||||
|
return AnyCodable.ArrayTypeName as! T
|
||||||
|
case .dictionary:
|
||||||
|
return AnyCodable.DictionaryTypeName as! T
|
||||||
|
default:
|
||||||
|
fatalError("Unsupported type here")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if key.stringValue == "value" {
|
||||||
|
return try self.decoder.unbox(type: type, javaObject: self.jniStorage.javaObject)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fatalError("Unknown key: \(key.stringValue)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: K) throws -> KeyedDecodingContainer<NestedKey> where NestedKey : CodingKey {
|
||||||
|
throw JavaCodingError.notSupported("JavaAnyCodableContainer.nestedContainer(keyedBy: \(type), forKey: \(key))")
|
||||||
|
}
|
||||||
|
|
||||||
|
func nestedUnkeyedContainer(forKey key: K) throws -> UnkeyedDecodingContainer {
|
||||||
|
switch jniCodableType {
|
||||||
|
case .array:
|
||||||
|
return JavaArrayContainer(decoder: self.decoder, jniStorage: self.jniStorage)
|
||||||
|
case .dictionary:
|
||||||
|
return try JavaHashMapUnkeyedContainer(decoder: self.decoder, jniStorage: self.jniStorage)
|
||||||
|
default:
|
||||||
|
fatalError("Unsupported type here")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func superDecoder() throws -> Decoder {
|
||||||
|
throw JavaCodingError.notSupported("JavaAnyCodableContainer.superDecoder")
|
||||||
|
}
|
||||||
|
|
||||||
|
func superDecoder(forKey key: K) throws -> Decoder {
|
||||||
|
throw JavaCodingError.notSupported("JavaAnyCodableContainer.superDecoder(forKey: \(key)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension JavaDecoder {
|
extension JavaDecoder {
|
||||||
|
|
||||||
fileprivate func unbox<T: Decodable>(type: T.Type, javaObject: jobject) throws -> T {
|
fileprivate func unbox<T: Decodable>(type: T.Type, javaObject: jobject) throws -> T {
|
||||||
|
@ -555,6 +653,27 @@ extension JavaDecoder {
|
||||||
let pathString = JNI.api.CallObjectMethodA(JNI.env, javaObject, ObjectToStringMethod, nil)
|
let pathString = JNI.api.CallObjectMethodA(JNI.env, javaObject, ObjectToStringMethod, nil)
|
||||||
return URL(string: String(javaObject: pathString)) as! T
|
return URL(string: String(javaObject: pathString)) as! T
|
||||||
}
|
}
|
||||||
|
else if type == AnyCodable.self {
|
||||||
|
let cls = JNI.api.GetObjectClass(JNI.env, javaObject)
|
||||||
|
let javaClassName = JNI.api.CallObjectMethodA(JNI.env, cls, ClassGetNameMethod, nil)
|
||||||
|
let className = String(javaObject: javaClassName).replacingOccurrences(of: ".", with: "/")
|
||||||
|
JNI.DeleteLocalRef(cls)
|
||||||
|
JNI.DeleteLocalRef(javaClassName)
|
||||||
|
let codableType: JNIStorageType
|
||||||
|
if className == ArrayListClassname {
|
||||||
|
codableType = .array
|
||||||
|
}
|
||||||
|
else if className == HashMapClassname {
|
||||||
|
codableType = .dictionary
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
codableType = .object(className: className)
|
||||||
|
}
|
||||||
|
let obj = JNI.api.NewLocalRef(JNI.env, javaObject)!
|
||||||
|
let storageObject = JNIStorageObject(type: .anyCodable(codable: codableType), javaObject: obj)
|
||||||
|
self.storage.append(storageObject)
|
||||||
|
return try T.init(from: self)
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
let stringType = "\(type)"
|
let stringType = "\(type)"
|
||||||
let storageObject: JNIStorageObject
|
let storageObject: JNIStorageObject
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import CoreFoundation
|
import CoreFoundation
|
||||||
import java_swift
|
import java_swift
|
||||||
|
import AnyCodable
|
||||||
|
|
||||||
public enum MissingFieldsStrategy: Error {
|
public enum MissingFieldsStrategy: Error {
|
||||||
case `throw`
|
case `throw`
|
||||||
|
@ -26,6 +27,7 @@ indirect enum JNIStorageType {
|
||||||
case object(className: String)
|
case object(className: String)
|
||||||
case array
|
case array
|
||||||
case dictionary
|
case dictionary
|
||||||
|
case anyCodable(codable: JNIStorageType)
|
||||||
|
|
||||||
var sig: String {
|
var sig: String {
|
||||||
switch self {
|
switch self {
|
||||||
|
@ -35,6 +37,8 @@ indirect enum JNIStorageType {
|
||||||
return "L\(ArrayListClassname);"
|
return "L\(ArrayListClassname);"
|
||||||
case .dictionary:
|
case .dictionary:
|
||||||
return "L\(HashMapClassname);"
|
return "L\(HashMapClassname);"
|
||||||
|
case .anyCodable(let codable):
|
||||||
|
return codable.sig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,6 +120,9 @@ open class JavaEncoder: Encoder {
|
||||||
case let .object(className):
|
case let .object(className):
|
||||||
let container = JavaObjectContainer<Key>(referencing: self, codingPath: self.codingPath, javaClass: className, jniStorage: storage)
|
let container = JavaObjectContainer<Key>(referencing: self, codingPath: self.codingPath, javaClass: className, jniStorage: storage)
|
||||||
return KeyedEncodingContainer(container)
|
return KeyedEncodingContainer(container)
|
||||||
|
case .anyCodable:
|
||||||
|
let container = JavaAnyCodableContainer<Key>(referencing: self, codingPath: self.codingPath, jniStorage: storage)
|
||||||
|
return KeyedEncodingContainer(container)
|
||||||
default:
|
default:
|
||||||
fatalError("Only keyed containers")
|
fatalError("Only keyed containers")
|
||||||
}
|
}
|
||||||
|
@ -190,7 +197,7 @@ fileprivate class JavaObjectContainer<K : CodingKey> : KeyedEncodingContainerPro
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
if self.encoder.missingFieldsStrategy == .ignore {
|
if self.encoder.missingFieldsStrategy == .ignore {
|
||||||
// Ignore
|
NSLog("Ignore error: \(error)")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw error
|
throw error
|
||||||
|
@ -207,7 +214,8 @@ fileprivate class JavaObjectContainer<K : CodingKey> : KeyedEncodingContainerPro
|
||||||
}
|
}
|
||||||
|
|
||||||
public func superEncoder() -> Encoder {
|
public func superEncoder() -> Encoder {
|
||||||
preconditionFailure("Not implemented: superEncoder")
|
self.encoder.javaObjects.append(self.jniStorage)
|
||||||
|
return self.encoder
|
||||||
}
|
}
|
||||||
|
|
||||||
public func superEncoder(forKey key: Key) -> Encoder {
|
public func superEncoder(forKey key: Key) -> Encoder {
|
||||||
|
@ -423,6 +431,84 @@ class JavaEnumValueEncodingContainer: SingleValueEncodingContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - AnyCodable Containers
|
||||||
|
fileprivate class JavaAnyCodableContainer<K : CodingKey> : KeyedEncodingContainerProtocol {
|
||||||
|
|
||||||
|
typealias Key = K
|
||||||
|
|
||||||
|
// MARK: Properties
|
||||||
|
/// A reference to the encoder we're writing to.
|
||||||
|
private let encoder: JavaEncoder
|
||||||
|
private let jniStorage: JNIStorageObject
|
||||||
|
|
||||||
|
/// The path of coding keys taken to get to this point in encoding.
|
||||||
|
private(set) public var codingPath: [CodingKey]
|
||||||
|
|
||||||
|
// MARK: - Initialization
|
||||||
|
/// Initializes `self` with the given references.
|
||||||
|
fileprivate init(referencing encoder: JavaEncoder, codingPath: [CodingKey], jniStorage: JNIStorageObject) {
|
||||||
|
self.encoder = encoder
|
||||||
|
self.codingPath = codingPath
|
||||||
|
self.jniStorage = jniStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
private var javaObject: jobject {
|
||||||
|
return jniStorage.javaObject
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - KeyedEncodingContainerProtocol Methods
|
||||||
|
public func encodeNil(forKey key: Key) throws {
|
||||||
|
throw JavaCodingError.notSupported("JavaObjectContainer.encodeNil(forKey: \(key)")
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode<T : Encodable>(_ value: T, forKey key: Key) throws {
|
||||||
|
if key.stringValue == "typeName" {
|
||||||
|
// ignore typeName
|
||||||
|
return
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
let jniObject = try self.encoder.box(value)
|
||||||
|
self.jniStorage.javaObject = JNI.api.NewLocalRef(JNI.env, jniObject.javaObject)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
if self.encoder.missingFieldsStrategy == .ignore {
|
||||||
|
NSLog("Ignore error: \(error)")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> {
|
||||||
|
preconditionFailure("Not implemented: nestedContainer")
|
||||||
|
}
|
||||||
|
|
||||||
|
public func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
|
||||||
|
switch self.jniStorage.type {
|
||||||
|
case let .anyCodable(codable):
|
||||||
|
switch codable {
|
||||||
|
case .dictionary:
|
||||||
|
return JavaHashMapUnkeyedContainer(referencing: self.encoder, codingPath: self.codingPath, jniStorage: self.jniStorage)
|
||||||
|
case .array:
|
||||||
|
return JavaArrayContainer(referencing: self.encoder, codingPath: self.codingPath, jniStorage: self.jniStorage)
|
||||||
|
default:
|
||||||
|
fatalError("Only single containers")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
fatalError("Only single containers")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func superEncoder() -> Encoder {
|
||||||
|
preconditionFailure("Not implemented: superEncoder")
|
||||||
|
}
|
||||||
|
|
||||||
|
public func superEncoder(forKey key: Key) -> Encoder {
|
||||||
|
preconditionFailure("Not implemented: superEncoder")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension JavaEncoder {
|
extension JavaEncoder {
|
||||||
|
|
||||||
fileprivate func box<T: Encodable>(_ value: T) throws -> JNIStorageObject {
|
fileprivate func box<T: Encodable>(_ value: T) throws -> JNIStorageObject {
|
||||||
|
@ -516,6 +602,31 @@ extension JavaEncoder {
|
||||||
let uriObject = JNI.check(JNI.CallStaticObjectMethod(UriClass, methodID: UriConstructor!, args: args), &locals)
|
let uriObject = JNI.check(JNI.CallStaticObjectMethod(UriClass, methodID: UriConstructor!, args: args), &locals)
|
||||||
storage = JNIStorageObject.init(type: .object(className: UriClassname), javaObject: uriObject!)
|
storage = JNIStorageObject.init(type: .object(className: UriClassname), javaObject: uriObject!)
|
||||||
}
|
}
|
||||||
|
else if T.self == AnyCodable.self {
|
||||||
|
let anyCodableValue = value as! AnyCodable
|
||||||
|
let storageType: JNIStorageType
|
||||||
|
let fullClassName: String
|
||||||
|
if anyCodableValue.typeName == AnyCodable.DictionaryTypeName {
|
||||||
|
fullClassName = HashMapClassname
|
||||||
|
storageType = .anyCodable(codable: .dictionary)
|
||||||
|
}
|
||||||
|
else if anyCodableValue.typeName == AnyCodable.ArrayTypeName {
|
||||||
|
fullClassName = ArrayListClassname
|
||||||
|
storageType = .anyCodable(codable: .array)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fullClassName = package + "/" + anyCodableValue.typeName
|
||||||
|
storageType = .anyCodable(codable: .object(className: fullClassName))
|
||||||
|
}
|
||||||
|
let javaClass = try JNI.getJavaClass(fullClassName)
|
||||||
|
let emptyConstructor = try JNI.getJavaEmptyConstructor(forClass: fullClassName)
|
||||||
|
guard let javaObject = JNI.api.NewObjectA(JNI.env, javaClass, emptyConstructor, nil) else {
|
||||||
|
throw JavaCodingError.cantCreateObject(fullClassName)
|
||||||
|
}
|
||||||
|
storage = JNIStorageObject(type: storageType, javaObject: javaObject)
|
||||||
|
javaObjects.append(storage)
|
||||||
|
try anyCodableValue.encode(to: self)
|
||||||
|
}
|
||||||
else if Mirror(reflecting: value).displayStyle == .enum {
|
else if Mirror(reflecting: value).displayStyle == .enum {
|
||||||
let fullClassName = package + "/" + String(describing: type(of: value))
|
let fullClassName = package + "/" + String(describing: type(of: value))
|
||||||
// We don't create object for enum. Should be created at JavaEnumValueEncodingContainer
|
// We don't create object for enum. Should be created at JavaEnumValueEncodingContainer
|
||||||
|
@ -539,8 +650,8 @@ extension JavaEncoder {
|
||||||
storageType = .object(className: fullClassName)
|
storageType = .object(className: fullClassName)
|
||||||
}
|
}
|
||||||
let javaClass = try JNI.getJavaClass(fullClassName)
|
let javaClass = try JNI.getJavaClass(fullClassName)
|
||||||
let emptyContructor = try JNI.getJavaEmptyConstructor(forClass: fullClassName)
|
let emptyConstructor = try JNI.getJavaEmptyConstructor(forClass: fullClassName)
|
||||||
guard let javaObject = JNI.api.NewObjectA(JNI.env, javaClass, emptyContructor, nil) else {
|
guard let javaObject = JNI.api.NewObjectA(JNI.env, javaClass, emptyConstructor, nil) else {
|
||||||
throw JavaCodingError.cantCreateObject(fullClassName)
|
throw JavaCodingError.cantCreateObject(fullClassName)
|
||||||
}
|
}
|
||||||
storage = JNIStorageObject(type: storageType, javaObject: javaObject)
|
storage = JNIStorageObject(type: storageType, javaObject: javaObject)
|
||||||
|
|
Loading…
Reference in New Issue